[comp.lang.c] Variable structure size -- ANSI ?

berg@marvin.e17.physik.tu-muenchen.de (Stephen R. van den Berg) (04/11/91)

Michael N Johnston writes:
]>struct foo {
]>unsigned short recsize;
]>unsigned short num;
]>char info [24];
]>byte flags;
]>char filename[1]
]>};
]>Where, foo.filename is a placeholder for a variable length string.

]If you plan to store a char array in filename DON'T. Use char *filename
]and point this to your actual array. Using your origional declaration
]and doing something like strcpy(foo_ptr->filename, "abcde") will lead
]to disaster.

Why should this lead to disaster?   Is this not allowed by ANSI?
If you can make sure that you have malloced more than enough space for the
structure, shouldn't you be able to use all this space by doing just that?
--
Sincerely,                 berg@marvin.e17.physik.tu-muenchen.de
           Stephen R. van den Berg.
"I code it in 5 min, optimize it in 90 min, because it's so well optimized:
it runs in only 5 min.  Actually, most of the time I optimize programs."

harry@matilda.uk.sun.com (Harry Protoolis - Sun EHQ) (04/13/91)

|> Michael N Johnston writes:
|> ]>struct foo {
|> ]>unsigned short recsize;
|> ]>unsigned short num;
|> ]>char info [24];
|> ]>byte flags;
|> ]>char filename[1]
|> ]>};
|> ]>Where, foo.filename is a placeholder for a variable length string.
|> 

A question really, does the standard *guarantee* the physical order of structure
elements ? I looked in K&R 2 and couldn't find anything.

Like, my smart compiler couldn't decide to 'shuffle' them around for reasons
best known to itself could it ?, ... or could it ?

IMHO the technique used above is inferior to using char *filename and mallocing
the space separately simply for reasons of clarity, and if a compiler might 
shuffle structure elements around it could one day lead to some rather curious 
bugs ...

Harry
--- 
(smart Internet mailers) harry.protoolis@uk.sun.com
(smart JANET mailers) harry.protoolis@sun-microsystems.co.uk
(dumb uucp mailers) ...!sun!sunuk!harry.protoolis

'When I give food to the poor they call me a saint.
 When I ask why the poor have no food they call me a communist.'
         - Dom Helder Camara

jlg@cochiti.lanl.gov (Jim Giles) (04/13/91)

> A question really, does the standard *guarantee* the physical order of structure
> elements ? I looked in K&R 2 and couldn't find anything.

Yes.  The standard guarantees that elements of a struct will be in the
order specified in the declaration.  However, the standard also permits
the compiler to insert padding as it sees fit.  So, using structs to
describe a packed table from another machine (or, from another language
on the same machine) is not reliable.

The above is true for the example given.  However, if the struct contains
bit fields, there is a further complication.  The order of allocation
of bit fields within a "storage unit" (the resolution limit of the
machine's addresses) is implementation defined (it is intended to be
_either_ "little-endian" or "big-endian", but can be any order the
implementor decides).  And, the implementor is still permitted any 
padding he likes - including putting each bit field into a separate
storage unit.

Of course, if you don't need portable code, you can experiment to
determine the actual packing structure of your host machine.

J. Giles

willcr@bud.sos.ivy.isc.com (Will Crowder) (04/13/91)

In article <6246@male.EBay.Sun.COM>, harry@matilda.uk.sun.com (Harry
Protoolis - Sun EHQ) writes:

> |> Michael N Johnston writes:
> |> ]>struct foo {
> |> ]>unsigned short recsize;
> |> ]>unsigned short num;
> |> ]>char info [24];
> |> ]>byte flags;
> |> ]>char filename[1]
> |> ]>};
> |> ]>Where, foo.filename is a placeholder for a variable length string.
> |> 
> 
> A question really, does the standard *guarantee* the physical order of
> structure elements ? I looked in K&R 2 and couldn't find anything.

The ANSI standard guarantees that elements of a structure will be allocated
in the order declared.  However, there may be any amount of padding between
structure elements.  But yes, for

	struct foo {
		int a;
		int b;
	};

&foo.b is guaranteed to be greater then &foo.a.  Also, &foo is guaranteed
to be equal to &foo.a.

|> Harry
|> --- 

Hope this helps,

Will

--------------------------------------------------------------------------------
Will Crowder, MTS            | "An optimist sees a glass that's half full.  A
(willcr@ivy.isc.com)         |  pessimist sees a glass that's half empty.  An
INTERACTIVE Systems Corp.    |	engineer sees a glass that's twice as big as
			     |  it needs to be!"  -- unknown (at least, by me)

rogue@cellar.UUCP (Rogue Winter) (04/14/91)

willcr@bud.sos.ivy.isc.com (Will Crowder) writes:

> The ANSI standard guarantees that elements of a structure will be allocated
> in the order declared.  However, there may be any amount of padding between
> structure elements.  But yes, for
> 
> 	struct foo {
> 		int a;
> 		int b;
> 	};
> 
> &foo.b is guaranteed to be greater then &foo.a.  Also, &foo is guaranteed
> to be equal to &foo.a.
> 

Just a quick follow-up question: while

        struct foo
        {   short a;
            short b;
        }
is guaranteed to produce &b > &a, will

        struct bar
        {   short a,b;  }
also be guaranteed, or will the pointer order be compiler-dependent?


Rogue Winter      : "How can you say I only protected people in South
rogue@cellar.uucp : Philadelphia?  I protected people all over this city; it
uunet!cellar!rogue: didn't matter if they were in South Philadelphia or
Cellar 215/3369503: Northeast Philadelphia."  -- Frank Rizzo, 4/12/91

id8rld06@serss0.fiu.edu (Michael N Johnston) (04/14/91)

Stephen R. van den Berg writes:
]Michael N Johnston writes:
]]>struct foo {
]]>unsigned short recsize;
]]>unsigned short num;
]]>char info [24];
]]>byte flags;
]]>char filename[1]
]]>};
]]>Where, foo.filename is a placeholder for a variable length string.
]
]]If you plan to store a char array in filename DON'T. Use char *filename
]]and point this to your actual array. Using your origional declaration
]]and doing something like strcpy(foo_ptr->filename, "abcde") will lead
]]to disaster.
]
]Why should this lead to disaster?   Is this not allowed by ANSI?
]If you can make sure that you have malloced more than enough space for the
]structure, shouldn't you be able to use all this space by doing just that?

    Whether it is "permited" by ANSI or not I am not sure. However,
even if it is permited by the standard, it is rather poor coding style.
From the point of view of maintanance, consider what would happen if
you put the program aside for six months or a year. You are not likely
to remember every coding trick that the program uses when you finally
come back to it. Or say, you give the program to a freind and he (or you)
decides to modify it and adds another field to struct foo after filemane.
All of a sudden, the program stops working. Unless you remember (or he
figures out) that the order of fields in foo is important, there is
going to be a tough debugging session ahead.
    A much more maintainable way to accomplish the same thing is to use
char *filename and do structname.filename = malloc(...). Since you plan
to malloc storage for the struct this would mean two calls to malloc,
but the benefits would almost always outway the cost. Doing this makes
it clear that filename is pointing to an array rather than just being
a one character array.
    C makes several quick coding tricks easy but unless you are just
doing a one time "quick and dirty" program, they should generally be
avoided. OFTEN using them makes even a small program nearly
unmaintainable. Sometimes, they can really be helpful, but, this is
the exception and not the rule.

Mike
--
====================================================================
Michael Johnston
id8rld06@serss0.fiu.edu or
26793271x@servax.fiu.edu

willcr@bud.sos.ivy.isc.com (Will Crowder) (04/18/91)

In article <1D6c12w164w@cellar.UUCP>, rogue@cellar.UUCP (Rogue Winter) writes:

|> Just a quick follow-up question: while
|> 
|>         struct foo
|>         {   short a;
|>             short b;
|>         }
|> is guaranteed to produce &b > &a, will
|> 
|>         struct bar
|>         {   short a,b;  }
|> also be guaranteed, or will the pointer order be compiler-dependent?

struct bar {
	short a, b;
};

is syntactically equivalent to

struct bar {
	short a;
	short b;
};

so yes, the behavior is the same.

Will

--------------------------------------------------------------------------------
Will Crowder, MTS            | "That was setting #1.  Anyone want to see
(willcr@ivy.isc.com)         |  setting #2?"
INTERACTIVE Systems Corp.    |		-- Guinan