[comp.lang.c] Structure padding

zap@front.se (Svante Lindahl) (04/06/89)

Consider a struct consisting of a few character arrays, for example:

	stuct foo {
	    char bar[3];
	    char baz[6];
	    char frotz[4];
	} fred;

I need to know if I can safely assume that there will not be any
padding between the arrays.  I didn't think that this would be OK to
assume, but I've tried this with a few different machine and compiler
combos (Sun3/SunOS3.5+(cc|gcc), Sun4/SunOS4.0+cc, Pyramid9820/
OSx4.1+cc (%)) and none of them place any padding between the arrays.
--
% Pyramid's cc is not based on pcc.

(Note: I'm not talking about padding at the end of the struct; there
will often be padding after the last array to make the size of the
struct be a multiple of 2 or 4 bytes.)

-- 
Svante.Lindahl@front.se	 (path-net: uunet!front.se!svante)
			 (non-mx: Svante.Lindahl%front.se@uunet.uu.net)

chad@lakesys.UUCP (Chad Gibbons) (04/07/89)

In article <440@front.se> zap@front.se (Svante Lindahl) writes:
|Consider a struct consisting of a few character arrays, for example:
|	stuct foo {
|	    char bar[3];
|	    char baz[6];
|	    char frotz[4];
|	} fred;
|I need to know if I can safely assume that there will not be any
|padding between the arrays.

	I don't think so.  I know for sure that Intel machines do place
padding in appropriate areas in order to force alignment on even word
addresses.  I believe that Microsoft compilers have an option to
eliminate this, but that slows down the program.  I had a list of
machines that require objects to start on even word addresses, but I
can't find it....anyone? anyone?
-- 
D. Chadwick Gibbons, chad@lakesys.lakesys.com, ...!uunet!marque!lakesys!chad

paulc@microsoft.UUCP (Paul Canniff 2/1011) (04/09/89)

In article <440@front.se> zap@front.se (Svante Lindahl) writes:
|Consider a struct consisting of a few character arrays, for example:
|	stuct foo {
|	    char bar[3];
|	    char baz[6];
|	    char frotz[4];
|	} fred;
|I need to know if I can safely assume that there will not be any
|padding between the arrays.

Don't unless you have a real size problem.  But read on for details ...

Microsoft C does indeed have options to enable or disbale padding of
structures to WORD slignment, for faster operations on Intel's processors.
The default is WORD alignment.  The option can be set to BYTE,
DWORD or WORD.  (See /Zp in MSC user's ref).

But ... even in the Intel world, the example above would not be effected
since the arrays are of type char, and will (theoretically) be accessed
a byte at a time.  So the compiler doesn't bother to word-align the
elements.

The moral ... you can probably assume byte alignment, 
since most C compilers will have to aimplement it (at whatever
cost to performance), but make a note of it in your porting instructions!

kremer@cs.odu.edu (Lloyd Kremer) (04/10/89)

In article <440@front.se> zap@front.se (Svante Lindahl) writes:

>Consider a struct consisting of a few character arrays, for example:
>
>	stuct foo {
>	    char bar[3];
>	    char baz[6];
>	    char frotz[4];
>	} fred;
>
>I need to know if I can safely assume that there will not be any
>padding between the arrays.
>(Note: I'm not talking about padding at the end of the struct; there
>will often be padding after the last array to make the size of the
>struct be a multiple of 2 or 4 bytes.)


It seems like a very unsafe thing to assume in code that is intended
to be maximally portable.  The dimension '3' is especially worrisome
in this regard.  However, there is a way to guarantee "no internal padding"
in a portable way.

You would simply define one big array (a C array is guaranteed to be
contiguous), and do the internal indexing yourself.  There should be no
performance degradation since the compiler would arrange for such indexing
anyway.  Also, some well-chosen macros could make using the strings easier.

How about:

	#define bar_siz 3
	#define baz_siz 6
	#define frotz_siz 4

	char fred[bar_siz + baz_siz + frotz_siz];

	#define bar (fred + 0)
	#define baz (fred + bar_siz)
	#define frotz (fred + bar_siz + baz_siz)
	/* the parentheses are vital to correct operation */

Now 'bar', 'baz', and 'frotz' can be treated just like normal character
arrays for accessing and indexing.  But beware the sizeof() operator!
The only *real* array is 'fred', which will not be directly referenced in the
code.  Thus,

	sizeof(fred) == 13
but
	sizeof(bar) == sizeof(baz) == sizeof(frotz) == sizeof(char *)

Capitalizing all the #define'd objects might help in remembering this pitfall.


					Hope this helps,

					Lloyd Kremer
					Brooks Financial Systems
					{uunet,sun,...}!xanth!brooks!lloyd

pekka@paix.ikp.liu.se (Pekka Akselin [The Mad Midnight Hacker]) (04/11/89)

In article <8392@xanth.cs.odu.edu> kremer@cs.odu.edu (Lloyd Kremer) writes:
>In article <440@front.se> zap@front.se (Svante Lindahl) writes:
>>Consider a struct consisting of a few character arrays, for example:
>>
>>	stuct foo {
>>	    char bar[3];
>>	    char baz[6];
>>	    char frotz[4];
>>	} fred;
>>
>>I need to know if I can safely assume that there will not be any
>>padding between the arrays.
[...]
>You would simply define one big array (a C array is guaranteed to be
>contiguous), and do the internal indexing yourself.  There should be no
>performance degradation since the compiler would arrange for such indexing
>anyway.  Also, some well-chosen macros could make using the strings easier.
[...]

How about this???

union {
	struct foo {
	    char	Bar[3];
	    char	Baz[6];
	    char	Frotz[4];
	} fred;
	char	SomeString[3 + 6 + 4];
} Strings;

#define bar	Strings.Bar
#define baz	Strings.Baz
#define	frotz	Strings.Frotz

Would there be padding between the Bar, Baz and Frotz arrays in this case?

My compiler generates the following line for the union above;

      .comm   _Strings,13

and the same for structure fred;

      .comm   _fred,13

Have a nice day!
-- 
Pekka					[The Mad Midnight Hacker Strikes Again]
_______________________________________________________________________________
pekka@paix.ikp.liu.se			...!uunet!enea!liuida!prodix!paix!pekka
Pekka Akselin, PA Mikroresurs, Sweden  (The Land Of The Mad Midnight Hacker 8-)

clive@ixi.UUCP (Clive) (04/13/89)

In article <124@paix.ikp.liu.se> pekka@paix.ikp.liu.se (Pekka Akselin [The Mad Midnight Hacker]) writes:
>>>[...]
>>>I need to know if I can safely assume that there will not be any
>>>padding between the arrays.
>
>How about this???
>
>union {
>	struct foo {
>	    char	Bar[3];
>	    char	Baz[6];
>	    char	Frotz[4];
>	} fred;
>	char	SomeString[3 + 6 + 4];
>} Strings;
>
>#define bar	Strings.Bar
>#define baz	Strings.Baz
>#define frotz	Strings.Frotz
>
>Would there be padding between the Bar, Baz and Frotz arrays in this case?

Yes there would. The size of the union is the maximum of the sizes of its elements.
Suppose that the compiler padded everything to 32-bit boundaries. Then your
declaration is effectively:

union {
	struct foo {
	    char	Bar[3];
            char	pad1[1];
	    char	Baz[6];
            char	pad2[2];
	    char	Frotz[4];
	} fred;
	char	SomeString[3 + 6 + 4];
} Strings;

and the memory layout is:

     Strings+:    0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
     fred:        --Bar--  #  ------Baz------- ##### ---Frotz---
     SomeString:  0  1  2  3  4  5  6  7  8  9 10 11 12 ########

where # indicates memory via this union element.

The answer to the original posting is "No". The only way to do it is some
technique which declares a single array and then breaks it up (e.g. via
#defines).
-- 
Clive D.W. Feather           clive@ixi.uucp
IXI Limited                  ...!mcvax!ukc!acorn!ixi!clive (untested)
                             +44 223 462 131

kremer@cs.odu.edu (Lloyd Kremer) (04/14/89)

In article <124@paix.ikp.liu.se> pekka@paix.ikp.liu.se (Pekka Akselin [The Mad  Midnight Hacker]) writes:
>How about this???
>
>union {
>	struct foo {
>	    char	Bar[3];
>	    char	Baz[6];
>	    char	Frotz[4];
>	} fred;
>	char	SomeString[3 + 6 + 4];
>} Strings;
>
>#define bar	Strings.Bar
>#define baz	Strings.Baz
>#define	frotz	Strings.Frotz
>
>Would there be padding between the Bar, Baz and Frotz arrays in this case?


First, the constructs Strings.Bar etc. are not valid; it would be
Strings.fred.Bar, and so on.

As to internal padding: within the array, no; within the structure, maybe.
So accessing Bar, Baz, and Frotz within Strings.SomeString may or may not be
equivalent to accessing them as Strings.fred.{member_name}.  The presence of
the array within the union has no effect on the compiler's policy regarding
internal padding within structures.


					Lloyd Kremer
					Brooks Financial Systems
					{uunet,sun....}!xanth!brooks!lloyd