Path: utzoo!attcan!uunet!munnari.oz.au!goanna!ok From: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) Newsgroups: comp.lang.c Subject: Re: sizeof(struct) and padding Message-ID: <4031@goanna.cs.rmit.oz.au> Date: 22 Oct 90 01:07:49 GMT References: <1229@sun13.scri.fsu.edu> Organization: Comp Sci, RMIT, Melbourne, Australia Lines: 55 In article <1229@sun13.scri.fsu.edu>, mayne@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.