1

I am writing USB device firmware... i have the following struct typedef

typedef struct  {
    uint8_t bLength;
    uint8_t bDescriptorType;
    uint16_t wTotalLength;
    uint8_t bNumInterfaces;
    uint8_t bConfigurationValue;
    uint8_t iConfiguration;
    uint8_t bmAttributes;
    uint8_t bMaxPower;
} usbtmc_config_descriptor;

By my count, this is 9 bytes, however when I do this

sprintf(temp, "size of config is %02x, %d", sizeof(usbtmc_config_descriptor), sizeof(usbtmc_config_descriptor));
prints(temp);

terminal spits out the following

size of config is 0a, 10

I am absolutely flumuxxed... If you are wondering the prints() method is just a method I wrote to print out a string through the UART to hyperterminal followed by \r\n for ease of use...

here is the whole method for those who think it is important

void prints(const char* message){
    MSS_UART_polled_tx_string(&g_mss_uart0, ((uint8_t *)message));
    unsigned char newline[2] = {0x0A, 0x0D};
    MSS_UART_polled_tx_string(&g_mss_uart0, newline);
}

some background info which may pertain to the situation, this is firmware code for a Cortex M3, Smartfusion Soc, using SoftConsole with GCC 4.4.1 CodeSourcery tools for compilation...

how is it possible that I am not getting a total of 9 for sizeof???? What am I missing???

artless noise
  • 21,212
  • 6
  • 68
  • 105
phriendtj
  • 96
  • 2
  • 10
  • a struct will always be a power of 2 in size(rounded up). The size and alignment will be according to the largest member/field within the struct. – user3629249 Oct 24 '14 at 00:47

2 Answers2

2

The largest element in you struct has two bytes. It has to be aligned at an offset divisible by 2.

Imagine you struct having a sizeof == 9, then if you have an array of these structs, the second element in the array will not have its member: wTotalLength correctly aligned.

For example:

Sizeof is 9, you have an array of structs usbtmc_config_descriptor[2] and you start at the address 0. The next element in the array of structs comes at the address 9. The member wTotalLength is at offset +2 which makes its address 11. Not correctly aligned.

Address of usbtmc_config_descriptor[0] is 0

Address of usbtmc_config_descriptor[1] is 9

Address of usbtmc_config_descriptor[1].wTotalLength is 11

2501
  • 25,460
  • 4
  • 47
  • 87
1

You observe structure padding (depending on the processor and its ABI). See e.g. this

You have a member wTotalLength which is of type uint16_t. It has to be two-bytes aligned on your architecture. So the entire structure has to be aligned to two bytes. Hence an extra gap of one byte is appended. Without such a gap, the odd elements of an array of usbtmc_config_descriptor-s would be misaligned. And accessing them might make a SIGBUS or alignment trap.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547