[net.lang.c] No. of elements in initialized array

colin@vu-vlsi.UUCP (Colin Kelley) (02/26/86)

We've got some code that looks like: (somewhat simplified here)

struct termentry {
        char name[MAX_ID_LEN];          /* name of graphics driver */
        unsigned int xmax,ymax;         /* screen dimensions */

} term_tbl[] = {
        {"hp",    HP_XMAX,    HP_YMAX},
        {"regis", REGIS_XMAX, REGIS_YMAX},
        {"tek",   TEK_XMAX,   TEK_YMAX}
};

This code takes advantage of the C compiler's ability to count the number of
initializers for term_tbl[], and automatically dimension term_tbl[] to that
size.  However, code that must look at term_tbl[] needs to know how many
elements it has.  The solution we're using now is:

#define TERMCOUNT (sizeof(term_tbl)/sizeof(struct termentry))

This works fine on both our Pyramid and our Vaxen.  BUT...is this the preferred
technique?  Isn't it possible on some machines that the structs may have to
be padded out to some arbitrary word boundary or something in order to fit
efficiently into the array (and thus sizeof(term_tbl) may not be an integer
multiple of sizeof(struct termentry))?  Or will C compilers guarantee that that
any necessary padding will be included in sizeof(struct)?

I assume this must be a pretty common problem.  I hope someone out there
can tell me whether our code is ok as is, or if I've overlooked some obvious
solution...Thanks!

                        -Colin Kelley  ..!{psuvax1,pyrnj}!vu-vlsi!colin

gwyn@BRL.ARPA (VLD/VMB) (03/03/86)

> ...  However, code that must look at term_tbl[] needs to know how many
> elements it has.  The solution we're using now is:
>
> #define TERMCOUNT (sizeof(term_tbl)/sizeof(struct termentry))
>
> This works fine on both our Pyramid and our Vaxen.  BUT...is this the preferred
> technique?  Isn't it possible on some machines that the structs may have to
> be padded out to some arbitrary word boundary or something in order to fit
> efficiently into the array (and thus sizeof(term_tbl) may not be an integer
> multiple of sizeof(struct termentry))?  Or will C compilers guarantee that that
> any necessary padding will be included in sizeof(struct)?

The padding is part of the "sizeof" the structure.

#define	number_of_elements(array)	(sizeof(array)/sizeof(array)[0])

This works unless your C compiler is badly broken.  (That CAN happen;
not very long ago I had to use one that insisted that sizeof a string
literal was equal to sizeof(char*).)

jst@abic.UUCP (Shack Toms) (03/05/86)

> We've got some code that looks like: (somewhat simplified here)
> 
> struct termentry {
>         char name[MAX_ID_LEN];          /* name of graphics driver */
>         unsigned int xmax,ymax;         /* screen dimensions */
> 
> } term_tbl[] = {
>         {"hp",    HP_XMAX,    HP_YMAX},
>         {"regis", REGIS_XMAX, REGIS_YMAX},
>         {"tek",   TEK_XMAX,   TEK_YMAX}
> };
> 
> This code takes advantage of the C compiler's ability to count the number of
> initializers for term_tbl[], and automatically dimension term_tbl[] to that
> size.  However, code that must look at term_tbl[] needs to know how many
> elements it has.  The solution we're using now is:
> 
> #define TERMCOUNT (sizeof(term_tbl)/sizeof(struct termentry))
> 
> This works fine on both our Pyramid and our Vaxen.  BUT...is this the preferred
> technique?  Isn't it possible on some machines that the structs may have to
> be padded out to some arbitrary word boundary or something in order to fit
> efficiently into the array (and thus sizeof(term_tbl) may not be an integer
> multiple of sizeof(struct termentry))?  Or will C compilers guarantee that that
> any necessary padding will be included in sizeof(struct)?
> 
> I assume this must be a pretty common problem.  I hope someone out there
> can tell me whether our code is ok as is, or if I've overlooked some obvious
> solution...Thanks!
> 
>                         -Colin Kelley  ..!{psuvax1,pyrnj}!vu-vlsi!colin

*** REPLACE THIS LINE WITH YOUR MESSAGE ***

I frequently use the macro

#define card(x) (sizeof(x)/sizeof *(x))

when called with an array name it will determine the number of elements
(I think of this as the cardinality of the array index set, hence the name.)

The problem with the padding of structs exists on the 68000, since word
references must be even byte aligned.  All of the compilers I have seen
therefore pad any struct which contains a value which must be aligned,
even if the struct which follows does not require the pad.
I always presumed that this was to ensure that the size of an array
was a multiple of the size of its elements.  I think that the consequences
of having variables of the same type require different sizes in
different circumstances would be dreadful,  sizeof (type) != sizeof (var)
where var is an expression of type "type".  I do not know if it is
actually required that the size of an array be a multiple of the size
of its elements, but I have never seen an implementation where this
is not true.

Shack Toms @ Allen-Bradley

jsdy@hadron.UUCP (Joseph S. D. Yao) (03/12/86)

In article <250@vu-vlsi.UUCP> colin@vu-vlsi.UUCP (Colin Kelley) writes:
>struct termentry { ... } term_tbl[] = { ... };
>  ...  However, code that must look at term_tbl[] needs to know how many
>elements it has.  The solution we're using now is:
>#define TERMCOUNT (sizeof(term_tbl)/sizeof(struct termentry))

This is one of the two classic solutions.  The other, if you have code
that steps through your structure, is to have an empty final member of
your structure array.  In your case, { "", 0, 0 }.  Then, code going
through the array can check for *tp->name == NUL, or for tp->xmax ==
0, or whatever you feel is best.

Incidentally, just as a matter of self-preservation in larger projects
(not to mention good style, sanity, etc.), it's been found good to
prefix each member of a structure with a "unique" prefix.  E.g.,
te_name, te_xmax, te_ymax.
-- 

	Joe Yao		hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}