[comp.lang.c] sizeof struct

afh@PacBell.COM (Alan Hobesh) (09/06/89)

The following c code prints the size of the definded structure to be 44,
when compiled on an AT&T 3B20 running UNIX V5.2.1.

/*------------------------------------------------------------*/
#include <stdio.h>
struct REC
{
  char   	vis_date[6];
  char   	vis_time[6]; 
  char   	vis_port[2];
  char   	vis_rec_type[2];
  char      	vis_seq_num[5];
  char         	vis_phone_num[10];
  char         	vis_switch[4];
  char         	vis_stop_dur[6];
  char          vis_cr;
} recbuf;

main()
{

        printf("struct = %d\n",sizeof(struct REC));

}
/*------------------------------------------------------------*/

However, when the code is downloaded to a PC and compiled using Turbo C,
the size of the structure is reported to be 42.

Why is there a difference and which is the correct size?

hartman@cbnewsc.ATT.COM (mark.a.hartman) (09/06/89)

In article <29722@pbhya.PacBell.COM> afh@PacBell.COM (Alan Hobesh) writes:
>
>
>The following c code prints the size of the definded structure to be 44,
>when compiled on an AT&T 3B20 running UNIX V5.2.1.
>

... structure and code omitted ...

>
>However, when the code is downloaded to a PC and compiled using Turbo C,
>the size of the structure is reported to be 42.
>
>Why is there a difference and which is the correct size?

The AT&T 3B20 compiler rounds structures up to an even word length,
in your case from 42 bytes to 44.  If you need code that is portable
between the two machines, try adding something like

	char	fill[2];

to the end of the structure to fill it out.  Then, "sizeof struct"
will be the same on both machines.

-- 
Mark Hartman                     hartman@ihlpm.att.com
                                 ..att!ihlpm!hartman
#include <std_disclaimer.h>

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/06/89)

In article <29722@pbhya.PacBell.COM> afh@PacBell.COM (Alan Hobesh) writes:
>The following c code prints the size of the definded structure to be 44,
>when compiled on an AT&T 3B20 running UNIX V5.2.1.
[...]
>However, when the code is downloaded to a PC and compiled using Turbo C,
>the size of the structure is reported to be 42.
>Why is there a difference and which is the correct size?

Both sizes are correct.  The difference is due to structure padding
(probably at the end of the structure, in this particular case).
C implementations differ in the amount and location of such padding.
If you intended the structure to describe an externally-imposed data
format, you need to be aware that there may be padding between the
structure members as well as at the end, so a simple roll-in of the
data into such a structure variable may not work right.

fredex@cg-atla.UUCP (Fred Smith) (09/06/89)

In article <29722@pbhya.PacBell.COM> afh@PacBell.COM (Alan Hobesh) writes:
>
>
>The following c code prints the size of the definded structure to be 44,
>when compiled on an AT&T 3B20 running UNIX V5.2.1.
>
     stuff deleted
>
>However, when the code is downloaded to a PC and compiled using Turbo C,
>the size of the structure is reported to be 42.
>
>Why is there a difference and which is the correct size?



Welcome to the world of "portability"!  This program reports two different
values because the compilers were implemented by different people.

Also, different processors have different data alignment restrictions. (I
do not know what processor is used in the 3B20, so I cannot speak to it.)

There is no requirement that the elements of a structure be packed
tightly together in memory, i.e., with no spaces between elements.
Obviously the Turbo C compiler is packing it tightly, to save space, while
the Unix compiler on the 3B20 is not. 

Members of the 80x86 family CAN
work with packed structures, but the accessing of those data structures
may be less efficient than if they were not packed, depending on the
particular structure's contents. Some other processors require word
alignment, or alignment on a boundary equal to the size of the item
stored there, or other such restrictions.


Hope this helps a little

Fred

henry@utzoo.uucp (Henry Spencer) (09/06/89)

In article <29722@pbhya.PacBell.COM> afh@PacBell.COM (Alan Hobesh) writes:
>The following c code prints the size of the definded structure to be 44,
>when compiled on an AT&T 3B20 running UNIX V5.2.1....
>However, when the code is downloaded to a PC and compiled using Turbo C,
>the size of the structure is reported to be 42.
>
>Why is there a difference and which is the correct size?

There is a difference because compilers use different rules for filling
in structures.  Both sizes are correct; code that assumes *any* specific
size for a struct is wrong.
-- 
V7 /bin/mail source: 554 lines.|     Henry Spencer at U of Toronto Zoology
1989 X.400 specs: 2200+ pages. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

karl@haddock.ima.isc.com (Karl Heuer) (09/07/89)

>Some other processors require word alignment, or alignment on a boundary
>equal to the size of the item stored there, or other such restrictions.

In this particular case, the processor doesn't require any special alignment
for the structure in question, but the implementation pads it anyway.  (As is
its right, silly though it may be.)  It's not a bug, just a misfeature.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

john@chinet.chi.il.us (John Mundt) (09/07/89)

In article <2951@cbnewsc.ATT.COM> hartman@cbnewsc.att.com (mark.a.hartman) writes:
>In article <29722@pbhya.PacBell.COM> afh@PacBell.COM (Alan Hobesh) writes:
>>
>>
>>The following c code prints the size of the definded structure to be 44,
>>when compiled on an AT&T 3B20 running UNIX V5.2.1.
>>However, when the code is downloaded to a PC and compiled using Turbo C,
>>the size of the structure is reported to be 42.
>>
>>Why is there a difference and which is the correct size?
>
>The AT&T 3B20 compiler rounds structures up to an even word length,
>in your case from 42 bytes to 44.  If you need code that is portable
>between the two machines, try adding something like
>
>	char	fill[2];
>
>to the end of the structure to fill it out.  Then, "sizeof struct"
>will be the same on both machines.


That is no guarantee that the two structures will be portable between
both machines.  Granted, both will be the same length, but the offset
to different members of the structure can vary.

I did not see the original structure, so if it was something like

struct foo {
	char fee[42];
};

there would be no problem, but also no need to have a structure.


However, if it were something as simple as

struct foo {
	int x;
	char y[38];
};

y could be offset 2 or 4 bytes from the beginning of the structure.
Further, if it were

struct foo {
	char y[37];
	int x;
};

then x could conceivably be at an offset of 37, 38, 40, or 48
depending on the system, the size of the word, and where different
types must be located.  Moving structures from disk to different
machines is not always so straight forward.  Much easier to convert
to ascii delimited strings and back again.

-- 
---------------------
John Mundt   Teachers' Aide, Inc.  P.O. Box 1666  Highland Park, IL
john@chinet.chi.il.us
(312) 998-5007 (Day voice) || -432-8860 (Answer Mach) && -432-5386 Modem  

scs@hstbme.mit.edu (Steve Summit) (09/07/89)

In article <2951@cbnewsc.ATT.COM> hartman@cbnewsc.att.com (mark.a.hartman) writes:
>The AT&T 3B20 compiler rounds structures up to an even word length,
>in your case from 42 bytes to 44.  If you need code that is portable
>between the two machines, try adding something like
>	char	fill[2];
>to the end of the structure to fill it out.  Then, "sizeof struct"
>will be the same on both machines.

If you need code that is portable between machines, don't rig it
up so that you depend on things like structure sizes.  One way to
depend on structure size (and arrangement, and byte order, etc.)
is to pass data between the machines (over the network, or on
magnetic media) by writing and reading whole structures.  A much
better approach is to write and read an ASCII, machine-
independent format.

If you must pad a structure out to some known size, a common
technique is to stick it in a union along with a buffer of the
desired size:

	union tblock {		/* from memory; can't find tar.c or tar.h */
		struct header {
			char name[100];
			char uid[8];
			char linktype;
		} header;
		char dummy[512];
	};

As long as sizeof(struct header) is less than 512,
sizeof(union tblock) will be exactly 512.  (This used to be the
case; one of the ANSI C experts will now point out that some
clause in the standard allows a compiler writer to implement
things such that sizeof(struct header) could be almost anything.)

                                      Steve Summit

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/07/89)

In article <14529@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes:
>In this particular case, the processor doesn't require any special alignment
>for the structure in question, but the implementation pads it anyway.  (As is
>its right, silly though it may be.)  It's not a bug, just a misfeature.

It's not necessarily silly.  When the first VAX C compiler was implemented,
the implementors decided to longword-align such things even though the VAX
is byte-addressable.  It made typical programs run faster on the only model
available at that time (VAX-11/780).  That was due to the operation of the
memory buffer cache.

ray@philmtl.philips.ca (Raymond Dunn) (09/08/89)

In article <10945@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>In article <29722@pbhya.PacBell.COM> afh@PacBell.COM (Alan Hobesh) writes:
>>Why is there a difference [of sizes of struct on different machines]
>
>Both sizes are correct.  The difference is due to structure padding
>(probably at the end of the structure, in this particular case).
>C implementations differ in the amount and location of such padding.
>If you intended the structure to describe an externally-imposed data
>format, you need to be aware that there may be padding between the
>structure members as well as at the end, so a simple roll-in of the
>data into such a structure variable may not work right.

In MS 'C' the compiler can be made to pack structures tightly, at the expense
of the code space and execution time required to access the fields in a less
efficient manner.

In MSC 4.x, use the /Zp option switch. (see page 193 of the Users' Guide).

In MSC 5.x, use the /Zpn option switch or #pragma pack(n), where n defines 1,
2 or 4 byte boundaries.  (see page 100 of the Users' Guide).

Whether or not it's proper to use such language extensions to handle
externally imposed data formats is a discussion I'd rather not breach....

-- 
Ray Dunn.                    | UUCP: ..!uunet!philmtl!ray
Philips Electronics Ltd.     | TEL : (514) 744-8200  Ext: 2347
600 Dr Frederik Philips Blvd | FAX : (514) 744-6455
St Laurent. Quebec.  H4M 2S9 | TLX : 05-824090

dune@cbnewsl.ATT.COM (Greg Pasquariello) (09/09/89)

In article <29722@pbhya.PacBell.COM> afh@PacBell.COM (Alan Hobesh) writes:
:
:
:The following c code prints the size of the definded structure to be 44,
:when compiled on an AT&T 3B20 running UNIX V5.2.1.

:However, when the code is downloaded to a PC and compiled using Turbo C,
:the size of the structure is reported to be 42.
:
:Why is there a difference and which is the correct size?


They are both correct.  The structure is padded to be word aligned.

Greg Pasquariello
att!picuxa!gpasq