[comp.lang.c] Initialization of a two-dimen. array of structures.

simpsong@ncoast.UUCP (03/14/87)

*** Line eater food ***

I have a structure like this:
===============================

struct of_stuff {
char *name
float value;
float another;
int counter;
}

stuff[20][30] = {
     {
        "joe", 1, 0, 12,
        "fred", 1, 0, 13,
        "carol",1, 0, 4 }
     ,
     { 
        "joe", 1, 0, 12,
        "fred", 1, 0, 13,
        "carol",1, 0, 4 }
     }

======================================

This works fine on VMS 4.5 (VMS C - 4.?) and on my PC using MS C 3.0.
However, when I tried it on a vax 11/780 running 4.3BSD and a Sun workstation
running whatever they call Unix (the latest 3.0 I believe), I got an error.
The error was repeated 4 times for each line that has a name in it
(like "joe"), the error said I was missing a }. (or something to that effect.)

My question is: What is the proper way to initialize a two dimensional
array of structures...

Thanks for any help, I thought I had it right till I tried BSD...

Greg

-- 
      Gregory R. Simpson       

UUCP: {ihnp4, seismo, decwrl, philabs, ucbvax}!decvax!cwruecmp!ncoast!simpsong
CSNET: ncoast!simpsong@case.CSNET     
ARPA:  ncoast!simpsong%case.CSNET@Csnet-Relay.ARPA

throopw@dg_rtp.UUCP (Wayne Throop) (03/20/87)

> simpsong@ncoast.UUCP (Gregory R. Simpson @ The North Coast)

> I have a structure like this:
>     struct of_stuff {
>         char *name; float value; float another; int counter;
>     }
>     stuff[20][30] = {{ [...value-list...] },{ [...value-list...] }};
> This works fine on VMS 4.5 (VMS C - 4.?) and on my PC using MS C 3.0.
> However, when I tried it on a vax 11/780 running 4.3BSD and a Sun workstation
> running whatever they call Unix (the latest 3.0 I believe), I got an error.
> The error was repeated 4 times for each line that has a name in it
> (like "joe"), the error said I was missing a }. (or something to that effect.)

Right.  You are missing a level of curly braces.  Some compilers are
forgiving of this, and some are not.  It is probably best to put in all
levels of braces necessary, even though I think K&R and X3J11 allow
some shortcuts.  This example linted and compiled correctly for me:

        typedef struct stuff_s {
            char *name; float value; float another; int counter;
        } stuff_t;

        stuff_t stuff[20][30] =
        {
            {
                { "00", 1, 2, 3 },
                { "01", 4, 5, 6 }
            },{
                { "10", 7, 8, 9 },
                { "11", 10, 11, 12 }
            }
        };

> My question is: What is the proper way to initialize a two dimensional
> array of structures...

Well, the idea I keep in mind is that what follows the equal sign is a
SINGLE VALUE that is the initial value of the object you are declaring.
If that object is an aggregate object (an array or a structure), it
becomes a curly-brace-enclosed comma-separated list of member initial
values.  From there we recurse.  So, since what we have here is an array
of array of struct of four members, we open a curly (we now are ready to
give a value for an array of struct of four members) open another curly
(we now are ready to give a value for a struct of four members) open
another curly (we are now ready to give a value for a struct member)
list four values separated by commas, close a curly, insert a comma (we
are now back up one level, giving the next value for an array of struct
of four members), open a curly.... and so on and on.

Note that in the example I've given, I've initialized stuff[0][0],
stuff[0][1], stuff[1][0], and stuff[1][1].  The problem is, in the
original example, it wasn't totally clear just what was being
initialized to what.  The extra level of curly braces makes it
unambiguous.

--
Big Mac had a heart attack in the back of a yellow cab,
After he'd stiffed his waitress and run out on his tab.
By the time the sound of the siren said the ambulance was coming,
His heart had stopped beating, but the meter was still running.
Life is hard.
                                --- Timbuk3
-- 
Wayne Throop      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw

michael@slovax.UUCP (03/20/87)

> I have a structure like this:
> ===============================
> 
> struct of_stuff {
> char *name
> float value;
> float another;
> int counter;
> }
> 
> stuff[20][30] = {
>      {
>         "joe", 1, 0, 12,
>         "fred", 1, 0, 13,
>         "carol",1, 0, 4 }
>      ,
>      { 
>         "joe", 1, 0, 12,
>         "fred", 1, 0, 13,
>         "carol",1, 0, 4 }
>      }
> 
> 
> ... when I tried it on a vax 11/780 running 4.3BSD and a Sun workstation
> running whatever they call Unix (the latest 3.0 I believe), I got an error.
> 
>       Gregory R. Simpson       


Ditto here on BSD.  It compiled okay with the addition of another level of
matching {}:

stuff[20][30] = {
     {
        {"joe", 1, 0, 12},
        {"fred", 1, 0, 13},
        {"carol",1, 0, 4} }
     }

K&R p. 124 says, for a particular example, "... It would be more precise
to enclose initilizers for each 'row' or structure in braces, ... but the
inner braces are not necessary when the initializers are simple variables
or character strings, and when all are present."

Apparently some compilers prefer the inner braces. It doesn't hurt to have
them in either case.


Michael Longe'
R & D Associates
..!tikal!slovax!michael



------ standard disclaimer -------------------------------------------------

I work in C, and my employers know it.


------ usual exclaimer -----------------------------------------------------

Qui, moi?

mouse@mcgill-vision.UUCP (03/22/87)

In article <2173@ncoast.UUCP>, simpsong@ncoast.UUCP (Gregory R. Simpson @ The North Coast) writes:
> struct of_stuff {
> char *name
> float value;
> float another;
> int counter;
> }
> 
> stuff[20][30] = {
>      {
>         "joe", 1, 0, 12,
> [...]

> This works fine on VMS 4.5 (VMS C - 4.?) and on my PC using MS C 3.0.
> However, when I tried it on a vax 11/780 running 4.3BSD and a Sun
> workstation running whatever they call Unix (the latest 3.0 I
> believe), I got an error.  The error was repeated 4 times for each
> line that has a name in it (like "joe"), the error said I was missing
> a }. (or something to that effect.)

I copied the code from your posting and tried compiling it on 4.3.  It
produced three errors for each initialization line, the error saying "}
expected".  This leads me to believe that you were actually trying to
compile the above code.  This is important because what you posted is
missing a semicolon on the first element of the structure!!  In fact,
the *first* error message the compiler produced complained about this.

Generally, you should fix the first error first.  Then run through the
rest of the errors, fixing any that seem reasonable and forgetting
about any that don't seem to make sense.  This is because, as in this
case, one error can cause may others - this is termed "floodgating".

Bright note:  you do have the initialization syntax right.  (I could
argue about the placement of the braces, but style has nothing to do
with the *correctness* of the code.)

					der Mouse

Smart mailers: mouse@mcgill-vision.uucp
USA: {ihnp4,decvax,akgua,utzoo,etc}!utcsri!musocs!mcgill-vision!mouse
     think!mosart!mcgill-vision!mouse
ARPAnet: think!mosart!mcgill-vision!mouse@harvard.harvard.edu

meissner@dg_rtp.UUCP (03/23/87)

In article <340@slovax.UUCP> michael@slovax.UUCP (Michael Longe) writes:
(original example deleted, you've seen it before)
> ....  It compiled okay with the addition of another level of
> matching {}:
> 
> stuff[20][30] = {
>      {
>         {"joe", 1, 0, 12},
>         {"fred", 1, 0, 13},
>         {"carol",1, 0, 4} }
>      }
> 
> K&R p. 124 says, for a particular example, "... It would be more precise
> to enclose initilizers for each 'row' or structure in braces, ... but the
> inner braces are not necessary when the initializers are simple variables
> or character strings, and when all are present."
> 
> Apparently some compilers prefer the inner braces. It doesn't hurt to have
> them in either case.

The technical reason the compilers are spilt on this issue seems to be the
way the compilers are implemented.  Compilers implemented via top-down
recursive descent (ie, the original Ritchie PDP-11 C compiler, MANX, etc.)
will accept the minimal braces, wheras bottom up LALR based compilers (the
Johnson PCC compiler in particular) have difficulty with this.  The draft
ANSI standard says it is implementation defined what happens if you have
left some intermediate level of braces off.
-- 
	Michael Meissner, Data General	Uucp: ...mcnc!rti-sel!dg_rtp!meissner

It is 11pm, do you know what your sendmail and uucico are doing?

msb@sq.UUCP (03/26/87)

> The draft ANSI standard says it is implementation defined what
> happens if you have left some intermediate level of braces off.

Nope, at least not the October 1986 (public comment) draft.
Some earlier ones said only that this would be resolved
in a later draft; perhaps still earlier ones said it was
implementation dependent.

a
From section 3.5.6, page 62 (lines 3-17):

 #  An array of characters may be initialized by a string literal,
 #  optionally enclosed in braces.  Successive characters of the
 #  string literal (including the terminating null character if there
 #  is room or if no size for the array is specified) initialize the
 #  members of the array.
 #  
 #  Otherwise, the initializer for an object that has aggregate type
 #  shall be a brace-enclosed list of initializers for the members of
 #  the aggregate, written in increasing subscript or member order.
 #  
 #  If the aggregate contains members that are aggregates, the rules
 #  apply recursively to the subaggregates.  If the initializer of a
 #  subaggregate begins with a left brace, the succeeding initializers
 #  initialize the members of the subaggregate.  Otherwise, only enough
 #  initializers from the list are taken to account for the members of
 #  the first subaggregate; any remaining initializers are left to
 #  initialize the next member of the subaggregate of which the current
 #  aggregate is a part.
 #  
 #  If there are fewer initializers in a list than there are members of
 #  an aggregate, the remainder of the aggregate shall be initialized
 #  implicitly the same as objects that have static duration.

I think the above is almost incomprehensible without careful study,
but the example at lines 42-25 of the same page makes things clear:

 #  	struct { int a[3], b; } w[] = { { 1 }, 2 };
 #  
 #  is a definition with a partly bracketed initialization, which is
 #  not recommended programming practice.  It defines an array with two
 #  member structures:  w[0].a[0] is 1 and w[1].a[0] is 2; all the other
 #  elements are zero.

That is, the above is equivalent to:

	struct { ... } w[] = { { { 1 } }, { { 2 } } };

and therefore to

	struct { ... } w[] = { {{1,0,0}, 0}, {{2,0,0}, 0} };

Mark Brader, utzoo!sq!msb			C unions never strike!