Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!tut.cis.ohio-state.edu!bloom-beacon!adam.pika.mit.edu!scs From: scs@adam.pika.mit.edu (Steve Summit) Newsgroups: comp.lang.c Subject: Re: vector initialization Keywords: vectors, char** Message-ID: <11883@bloom-beacon.MIT.EDU> Date: 8 Jun 89 03:00:29 GMT References: <687@lakesys.UUCP> <17940@mimsy.UUCP> Sender: daemon@bloom-beacon.MIT.EDU Reply-To: scs@adam.pika.mit.edu (Steve Summit) Distribution: usa Lines: 79 In article <687@lakesys.UUCP> chad@lakesys.UUCP (Chad Gibbons) writes: >Question: is it possible to initialize a vector? >...in the context of something >along these lines (from a command list vector): > >typedef struct _com { > char **words; > int (*fcn)(); > short flags; >} COM; > >...and then initializing the structure in another module by: > >COM foo[] = { > { "one", "two", "three", NULL }, do_num, 0, > { "exit", "quit", NULL }, quit, 0 >}; > >That would be nice, but something tells me it isn't C, or anything else >like it. I may resort to allowing only a single word per structure, but >it would be more advantageous to use a list associated with a single >structure entry. In article <17940@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >You need an object of type `pointer to pointer to char'. An array of >pointer to char would suffice, if you could create one without giving >it a name, because it would decay into a pointer to pointer to char. >But you cannot create one without naming it... >For each of the two COM objects foo[0] and foo[1], you need a constant >value of type `char **'. So what we *can* do is this: > > char *xxx0[] = { "one", "two", "three", NULL }; > char *xxx1[] = { "exit", "quit", NULL }; > > COM foo[] = { > { xxx0, do_num, 0 }, > { xxx1, quit, 0 }, > }; The other way is to modify the declaration, so that you don't need a pointer: typedef struct { char *words[MAXWORDS]; int (*fcn)(); short flags; } COM; COM foo[] = { {{ "one", "two", "three", NULL }, do_num, 0,}, {{ "exit", "quit", NULL }, quit, 0,}, }; This has the advantage that you don't need to think of names for the placeholder pointers. It has the disadvantages that the number of entries is limited, and space is wasted if there are many lists with considerably fewer than MAXWORDS entries. Note that the initialization of this latter form is exactly as Chad speculated (although I have added extra braces and commas, as Chris did). In fact, you can leave out the explicit NULLs as list endmarkers, because uninitialized char *'s (in this case, the entries out to MAXWORDS) are guaranteed to be set to null pointers. (For God's sake, if you don't understand this, don't post a followup!) The code scanning the list would be well-advised to terminate after either seeing a NULL or exhausting MAXWORDS words, whichever comes first. Accessing the words list is otherwise (syntactically) identical to the full pointer version. The method using dummy arrays, which Chris illustrated, is generally preferable, especially if you don't mind making up names. I often write preprocessors for application-specific aggregate initializations of this sort, which generate the intermediate arrays and dummy names automatically. Steve Summit scs@adam.pika.mit.edu