sizeof(struct) and padding

Richard A. O'Keefe ok at goanna.cs.rmit.oz.au
Mon Oct 22 11:07:49 AEST 1990


In article <1229 at sun13.scri.fsu.edu>, mayne at sun10.scri.fsu.edu (William (Bill) Mayne) writes:
> "Big deal!" you say? Actually it could make an important differnce
> if the structure is being written as a record to a file. Then  extra 
> file space will be used. Unless I intend to read or write arrays of
> records some of the time, changing the number of records handled, 
> with each operation, this is a real waste.

> The $64K question is: How do I portably get the actual size of
> a structure without padding when I need that rather than
> what sizeof() tells me?

There is no such thing as "the actual size of a structure without padding".
Much of the padding required for alignment is likely to be within the
record.  Consider
	struct foo { char a; double d; short s; void *p; };
			    ^                  ^
I've marked the two places that padding is likely to go on a machine that
requires 32-bit alignment for doubles and data pointers.  They are *inside*.

Suppose we could squeeze the padding out.  The size of the record with
padding is 20 bytes.  Without padding it'd be 15.  Big deal.  If you
order the fields in a struct thus:
	first long double
	then  double
	then  float
	then  pointer-to-function
	then  pointer
	then  long
	then  int
	then  short
	last  char
then all the padding required for alignment is likely to be at the end,
and on a 32-bit byte-addressed machine the total amount of padding is
likely to be at most 3 bytes.  This isn't going to be perfect on all
machines, but it's pretty good for most.  (It's a generalisation of the
ordering prudent Fortran programmers use within COMMON blocks.)

If you are only writing one or two records of a particular type to a
file, why do you care about the padding?  If you are writing thousands,
then you may well want to read and write arrays of them.

If it is absolutely essential that you write your records in the most
compact form, then don't use ``raw'' fwrite and fread.  Write your own

	int fwrite_foo(FILE *f, struct foo *p) { ... }
	int fread_foo(FILE *f, struct foo *p)  { ... }

functions that write/read the fields separately.

But above all, keep in mind that in C, there is no such thing as "the
actual size of a structure without padding".  "sizeof" is as actual 
as it ever gets.

-- 
Fear most of all to be in error.	-- Kierkegaard, quoting Socrates.



More information about the Comp.lang.c mailing list