Struct member alignment — different sizeof using 16-bit and 32-bit compiler

  • A+

I have a structure used to contruct messages to a control board I need to maintain software compatibility between a C167 16-bit Keil compiler and a 32-bit Tricore gcc compiler.

typedef struct {     unsigned char new_weld_status[2];     UINT32 new_weld_count;     UINT16 new_weld_fail_count; } NEW_PULSE_DATA; 

The array new_weld_status[2] takes up 2 bytes on the 16-bit compiler but 4 bytes on the 32-bit compiler. I was thinking of replacing all the new_weld_status[2] with a union when compiling with gcc. But is there a switch I can use for gcc that makes the chars fits/aligns in 2 bytes?


Note that your structure layout creates the problem on a 32-bit system. Many (most) 32-bit CPU architectures require 4-byte alignment for 32-bit words, thus the new_weld_count requires 'padding' to provide proper memory alignment.

typedef struct {     unsigned char   new_weld_status[2];   //a     //char padding_1[2]; //hidden padding     UINT32  new_weld_count;               //a     UINT16  new_weld_fail_count;          //a } NEW_PULSE_DATA; 

The following redefinition of your structure completely avoids the problem.

typedef struct {     UINT32  new_weld_count;               //a     UINT16  new_weld_fail_count;          //a     unsigned char   new_weld_status[2];   //a } NEW_PULSE_DATA; NEW_PULSE_DATA ex_PULSE_DATA; 

However, the above approach is not the approach typically to transport struct(ured) data across networks/over message transports. A more common and much better approach is to use a serialization/deserialization layer (aka marshalling) to place the structures into 'over the wire' formats. Your current approach is conflating the in-memory storage and addressing with the communication format.

//you need to decide on the size of wire format data, //Both ends of the protocol must agree on these sizes, #define new_weld_count_SZ sizeof(ex_PULSE_DATA.new_weld_count) #define new_weld_fail_count_SZ sizeof(ex_PULSE_DATA.new_weld_fail_count) #define new_weld_status_SZ sizeof(ex_PULSE_DATA.new_weld_status)  //Then you define a network/message format typedef struct {     byte new_weld_count[new_weld_count_SZ];     byte new_weld_fail_count[new_weld_count_SZ];     byte new_weld_status[new_weld_count_SZ]; } MESSAGE_FORMAT_PULSE_DATA; 

Then you would implement serialization & deserialization functions on both ends of the transport. The following example is simplistic, but conveys the gist of what you need.

byte* PULSE_DATA_serialize( MESSAGE_FORMAT_PULSE_DATA* msg, NEW_PULSE_DATA* data ) {     memcpy(&(msg->new_weld_count), data->new_weld_count, new_weld_count_SZ);     memcpy(&(msg->new_weld_fail_count), data->new_weld_fail_count, new_weld_fail_count_SZ);     memcpy(&(msg->new_weld_status), data->new_weld_status, new_weld_status_SZ);     return msg; }  NEW_PULSE_DATA* PULSE_DATA_deserialize( NEW_PULSE_DATA* data, MESSAGE_FORMAT_PULSE_DATA* msg ) {     memcpy(data->new_weld_count, &(msg->new_weld_count), new_weld_count_SZ);     memcpy(data->new_weld_fail_count, &(msg->new_weld_fail_count), new_weld_fail_count_SZ);     memcpy(data->new_weld_status, &(msg->new_weld_status), new_weld_status_SZ);     return msg; } 

Note that I have omitted the obligatory network byte order conversions, because I assume your have already worked out your byte order issues between the two cpu domains. If you have not considered byte-order (big-endian vs. little-endian), then you need to address that issue as well.

When you send a message, the sender does the following,

//you need this declared & assigned somewhere NEW_PULSE_DATA data; //You need space for your message MESSAGE_FORMAT_PULSE_DATA msg; result = send(PULSE_DATA_deserialize( &data, &msg )); 

When you receive a message, the recipient does the following,

//recipient needs this declared somewhere NEW_PULSE_DATA data; //Need buffer to store received data MESSAGE_FORMAT_PULSE_DATA msg; result = receive(&msg,sizeof(msg)); //appropriate receipt checking here... PULSE_DATA_deserialize( &data, &msg ); 


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: