This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Auto calculation of array size

Dear all,

For some reason, I need to declare an array like that

#define STRING2_DESCRIPTOR_LENGTH 16
BYTE code product_string_descriptor[] = {
	STRING2_DESCRIPTOR_LENGTH,
	0x03,
	'U', 0x00,
	'S', 0x00,
	'B', 0x00,
	' ', 0x00,
	'H', 0x00,
	'U', 0x00,
	'B', 0x00
};
When I add characters to the array, I also need to increase STRING_DESCRIPTOR_LENGTH manually.
Do you know some way to calculate the size of the array automatically?
I know in assembly, I can do something like that
product_string_descriptor:
	DB	end - $
	DB	0x03,
	DB	'U', 0x00
	DB	'S', 0x00
	DB	'B', 0x00
	DB	' ', 0x00
	DB	'H', 0x00
	DB	'U', 0x00
	DB	'B', 0x00
end:
How about in C?

  • I do not know of a way to do this purely at compile time. Perhaps I'm overlooking something this morning, but this is as close as I got:

    typedef struct
    	{
    	U8 length;
    	U8 val;
    	} StrDescHdr;
    
    
    U8 code pstr[] =
    	{ 'U', 0, 'S', 0, 'B', 0, ' ', 0, 'H', 0, 'U', 0, 'B', 0};
    
    typedef struct
    	{
    	StrDescHdr Hdr;
    	U8 code* value;
    	} StrDesc;
    
    StrDesc code psd =
    	{
    	{ sizeof(pstr) + sizeof(StrDesc), 3 },
    	pstr
    	};
    
    

    It costs two extra bytes of space for the pointer to the value, though.

    The problem is that the compiler won't know the size of something until it's seen the complete definition.

    Incidentally, I've found it better practice to explicitly declare the size of such fixed-length arrays with preprocessor symbols for size, rather than using empty square brackets. Instead of

    #define STRING2_DESCRIPTOR_LENGTH 16
    BYTE code product_string_descriptor[] = {

    prefer

    #define STRING2_DESCRIPTOR_LENGTH 16
    BYTE code product_string_descriptor[STRING2_DESCRIPTOR_LENGTH] = {

    This way, the compiler can generate a warning if you have too many or too few bytes in the initializer. You'll catch the error at compile time. With the first form, the compiler will accept however many entries the initializer happens to have, and you can't be sure the array is the correct length.

  • Hi Drew,

    Thanks for the suggestion of explicitly declare the size. But I think the compiler will not warn me if I have less initializer than the actual size. Most of the compiler will fill the rest of the array with zero. Am I right? Anyway, the compiler will still warn me if I supply more intializer than the actual size. So, I consider it as a better solution than before. Thanks again.

  • How about this:

    BYTE code table[] = ...
    
    #define TABLE_LEN (sizeof(table) / sizeof(table[0]))

    Jon

  • "I know in assembly, I can do something like..."

    So why not just do it in assembler, then?!

    If it's difficult in 'C' but easy in Assembler - surely the choice is obvious!!

    There is no problem linking 'C' & assembler in a single Project.

  • Hi Jon,

    You define TABLE_LEN after table[]. So, I think I can not use it in the initialization of table[]. But even if I define TABLE_LEN in front, I will still get the following warning
    warning C198: sizeof returns zero

  • Hi Andy,

    The reason for me to post this question is that I think if I am able to do it in C, my strength is getting stronger than before. Just like when you are learning Mathematics, will you feel better if you know more than one solution for some questions than the other?

  • OK, Then what about the following:

    #define USB_DESC "\03" "USB HUB"
    
    #define USB_DESC_LENGTH (sizeof(USB_DESC) - 1)  /*** -1 for null terminator ***/
    
    static unsigned char code product_string_descriptor[] = {
        USB_DESC_LENGTH,
        USB_DESC
    };

    This compiles just fine on my computer with C51 V7.05.

    Jon