Wireshark-dev: Re: [Wireshark-dev] R: Problems encountered on Windows building from a "source t
From: Guy Harris <guy@xxxxxxxxxxxx>
Date: Sat, 30 Dec 2006 13:04:50 -0800
Loris Degioanni wrote:

I've consistently seen both VC and gcc putting padding between values in an array, especially in a case like this one: there's good chance that dur will be at byte 4 instead of 2.

You've seen padding placed between arrays of "unsigned char"? On what CPU? I wouldn't expect that on x86 - there is a penalty for unaligned accesses with some x86 processors, but it is supported natively.

According to the GCC 4.1.1 manual, "the alignment of non-bit-field members of structures (C90 6.5.2.1, C99 6.7.2.1)" is "determined by ABI"; the i386 ABI manual at

	http://www.sco.com/developers/devspecs/abi386-4.pdf

says on page 28 that "char" and "unsigned char" are aligned on byte boundaries, and says on page 29 that "an array uses the same alignment as its elements" and that "each member [of a structure or union] is assigned to the lowest available offset with the appropriate alignment", which would put "dur" at byte 2. I can check some other ABI documents I have to see what they say, although I don't have any for ARM, for example.

Microsoft's documentation says

Every data object has an alignment-requirement. The alignment-requirement for all data except structures, unions, and arrays is either the size of the object or the current packing size (specified with either /Zp or the pack pragma, whichever is less). For structures, unions, and arrays, the alignment-requirement is the largest alignment-requirement of its members. Every object is allocated an offset so that

	offset % alignment-requirement == 0

The description of the /Zp option is:

When you specify this option, each structure member after the first is stored on either the size of the member type or n-byte boundaries (where n is 1, 2, 4, 8, or 16), whichever is smaller.

so it won't force stricter alignment.

The documentation also says of "#pragma pack(n)":

Specifies the value, in bytes, to be used for packing. The default value for n is 8. Valid values are 1, 2, 4, 8, and 16. The alignment of a member will be on a boundary that is either a multiple of n or a multiple of the size of the member, whichever is smaller.

so that reduces, but doesn't increase, alignment requirements.

To avoid the problem, I use #pragma pack with VC, and __attribute__((__packed__)) with GCC

typedef struct _foo
{
   char first;
   char second;
}__attribute__((__packed__))
foo;

With the right #ifdefs, you can easily make the thing portable.

What would you put inside the #ifdefs for Sun C, IBM xlc, and HP's C compiler - all three of those are used to compile Wireshark?