At 8:38 PM -0800 2000/02/16, Danny Epstein wrote:
>Here's a question for all you C gurus out there: What is the size of a struct that 
>contains an unbounded array? This is the only question about C I couldn't find the 
>answer to in Harbison & Steele's book.
>
>typedef struct
>{
>        ...
>        SomeType finalField[];
>} MyStruct
>
>... sizeof(MyStruct) ...
>
>So what is the size of this struct?

I don't know... you didn't provide the other fields. ;o)


>The answer, in practice, seems to be that the final field is considered to be of size 
>zero. (Of course, there can be padding before the final field, but that isn't the 
>issue.) I have never seen a book on C that explains this. Perhaps this is why some 
>programmers use char text[1] instead of char text[]?

Not quite, but you're close.

SomeType finalField[] is generally very well defined -- it's just alternate syntax for 
SomeType * finalField. Its size is that of a pointer, which is exactly what you've got 
in the structure definition: a pointer to an object of type SomeType. The ambiguity is 
whether or not the compiler will allocate for an instance of SomeType in an instance 
of MyStruct when you use this syntax, and that's highly compiler-dependent.

I'd guess what you're really confused about is that it's a variation on SomeType 
finalField[0] which is not well-defined, is technically invalid within a structure 
definition, and will generate results which also vary by compiler. Smarter compilers 
will make note of the [] or [0] on the last field and adjust sizeof(MyStruct) 
correctly to NOT include sizeof(SomeType) -- but only if the [] or [0] occurs on the 
last field of the structure. Any other location using [0] within the structure is an 
error regardless of compiler. BTW, it may help to think of [0] as equivalent to [-1] 
or any other invalid instance count (you may only declare "one or more" instances of 
the field within a structure in C).

Other compilers will error and abort the compilation, or treat the [] or [0] as [1] 
which is the next semi-logical choice, with or without warning, causing seemingly 
unpredictable results which may not be caught during testing.

By now you're probably thinking C is poorly designed for declaring variable length 
structures. Well, you're right. (Isn't this stuff fun? Don't answer that... I 
digress...)

The general consensus which makes all compilers happy seems to be to declare using [1] 
and then provide a macro or #define to use in place of sizeof(MyStruct) throughout 
your code which calculates the correct size of the structure (i.e. excludes the 
variable length last field, so that if you have no instances of the last field, the 
size of the structure is the sum of all previous fields and no more, adjusting for 
possible alignment padding).

OffsetOf is a good example of how to define a macro that calculates the correct size 
of a structure. Just pass your variable length last field as the member parameter and 
the result will be the true size of the structure excluding the last variable length 
field, in bytes, properly adjusted for any alignment padding that may occur if the 
field just prior to the last field is not aligned on the variable length member's 
natural boundary:

  #define OffsetOf(type, member) ((UInt32) &(((type *) 0)->member))

So in your example above, you would use OffsetOf(MyStruct, finalField) in place of 
sizeof(MyStruct) throughout your code for accurate, predictable results. "It's A Good 
Thing." -- Martha Stewart

Whew! Hope that helps... it's all from memory so I hope I didn't make any mistakes 
(apologies in advance if I did).

Regards,

Jim Schram
3Com/Palm Computing
Partner Engineering



-- 
For information on using the Palm Developer Forums, or to unsubscribe, please see 
http://www.palm.com/devzone/mailinglists.html

Reply via email to