Click here to Skip to main content
15,887,301 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
In my application I have a .h file that contains a struct which defines the header of a message that gets sent out on a UDP multicast socket. If I hand count the bytes of all the members of the struct I get 16 bytes, which is what it is supposed to be.

In my code where I use the struct, when I do a sizeof() on it I get 20 bytes. 4 bytes too large.

Does Microsoft add some baggage that isn't outwardly obvious??

Here's the struct.

C++
struct message_header_struct 
{

	unsigned char msg_header3:8; 
	unsigned char msg_header2:8;
	unsigned char msg_header1:8;
	unsigned char msg_header0:8;
	unsigned char reserved1:8;
	unsigned char reserved2:8;
	unsigned short msg_size; 				

	unsigned char pri_addr:4;	
					
	unsigned char zerobit4:1;
	unsigned char zerobit5:1;
	unsigned char statusbit:1;
	unsigned char zerobit6:1;
	
	unsigned char primaryport:1;     
	unsigned char zerobit7:1;
	unsigned char sec_addr:6;      
	
	unsigned char reserved3:8;
	msg_type_enum msg_type:8;	
	unsigned long sender_ID;	

};
Posted
Comments
Philippe Mori 14-Oct-15 12:57pm    
Using some testing and documentation, you should be able to determine how it works and have a better understanding.

Probably you forgot to specify the bit size for msg_size, and that may put data alignment if effect. Please check up.

One more thing: short and long are among so called "fundamental types"; their actual size depends on platform: https://msdn.microsoft.com/en-us/library/cc953fe1.aspx[^].

So, I would avoid using such types in the situations where you need exact bit size. For such purposes, C++11 (I do understand, this is not about VS 6.0) defines the following: http://en.cppreference.com/w/cpp/types/integer[^].

If you don't have C++11, you can use, for example, platform-specific definitions, such as Windows WORD, etc.

By the way, if you suspect some version of C++ coming with some version of Visual Studio does something wrong, you can always compare it with VS 2013 or VS 2015, Community Edition, which come free of charge.

—SA
 
Share this answer
 
v2
Comments
CPallini 14-Oct-15 4:02am    
5.
Sergey Alexandrovich Kryukov 14-Oct-15 11:14am    
Thank you, Carlo.
—SA
By default the Visual C/C++ compiler will align structure members at 8 byte boundaries inserting padding bytes if necessary. See the MSDN article Working with Packing Structures[^].

To avoid this, you can use pack pragma[^] to specifiy 1 byte alignment.

When using bit fields it is even more complicated. Then the compiler will only merge those fields that use the same integral type. But this can be used to ensure valid positions by using the same (largest) integral type for all bit field struct members. So you may define your structure as:
C++
#pragma pack(1)
struct message_header_struct
{
    unsigned msg_header3:8;
    unsigned msg_header2:8;
    unsigned msg_header1:8;
    unsigned msg_header0:8;
    unsigned reserved1:8;
    unsigned reserved2:8;
    unsigned msg_size:16;

    unsigned pri_addr:4;

    unsigned zerobit4:1;
    unsigned zerobit5:1;
    unsigned statusbit:1;
    unsigned zerobit6:1;

    unsigned primaryport:1;
    unsigned zerobit7:1;
    unsigned sec_addr:6;

    unsigned reserved3:8;
    unsigned msg_type:8;
    unsigned sender_ID:32;
};
#pragma pack()


[EDIT]
This has not changed for many years and should apply to all Visual versions since 6.0.
 
Share this answer
 
v2
Comments
Frankie-C 16-Oct-15 8:13am    
Jochen you're right. From C11 standard - 6.7.2.1 Structure and union specifiers:
"An implementation may allocate any addressable storage unit large enough to hold a bitfield.
If enough space remains, a bit-field that immediately follows another bit-field in a
structure shall be packed into adjacent bits of the same unit. If insufficient space remains,
whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is
implementation-defined. The order of allocation of bit-fields within a unit (high-order to
low-order or low-order to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified."

So bitfields of same type will be packed together.
I can add that because this is often used for packing hardware registers fields in structures, it is very unlikely that it will change, or a lot of OS and driver code will need fixes...

P.S. the order of allocation is generally the same of processor endianess. On X86 (little endian) runs from low to high order.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900