[comp.lang.c] static list initialization

ajw@donk.UUCP (ajw) (10/15/88)

Here's a fragment of code I find myself staring at glumly from
time to time.  It sets up the nucleus of a 2-way list, into
which extra malloc'd nodes will be inserted.

    struct whatever {
        struct whatever *next;            /* next node */
        struct whatever *prev;            /* previous node */
        int    eresting_stuff;            /* blah, blah, ... */
    };
    extern struct whatever tail;
    static struct whatever head = { &tail, (struct whatever *)0 };
    static struct whatever tail = { (struct whatever *)0, &head };

Without the 'extern', the compiler can't initialize 'head'.  But
with it, I get a 'non-standard extension' warning, although
everything works just fine.

Question is, is there a way to achieve this initialization within
the letter of the law, leaving 'head' and 'tail' both static?

If you want to e-mail, please use addresses below.  Ta muchly.

-- Alan Waldock                 ...{tektronix|sun}!ogcvax!omepd!ihf1!mdt!ajw
Intel Corp, HF2-37               OR            ...uunet!littlei!ihf1!mdt!ajw
5200 NE Elam Young Pkwy           OR EVEN               ajw@mdt.hf.intel.com
Hillsboro, OR. 97124-6497          OR IF ALL ELSE FAILS       (503) 696-2478
                                
Opinions individual author's. Read before breaking seal. No warranty implied.

joe@modcomp.UUCP (10/16/88)

> Here's a fragment of code I find myself staring at glumly from time to time.
> It sets up the nucleus of a 2-way list, into which extra malloc'd nodes will
> be inserted.
>
>     struct whatever {
>         struct whatever *next;            /* next node */
>         struct whatever *prev;            /* previous node */
>         int    eresting_stuff;            /* blah, blah, ... */
>     };
>     extern struct whatever tail;
>     static struct whatever head = { &tail, (struct whatever *)0 };
>     static struct whatever tail = { (struct whatever *)0, &head };
>
> Without the 'extern', the compiler can't initialize 'head'.  But with it, I
> get a 'non-standard extension' warning, although everything works just fine.

This kind of initialization can only be safely done at run time.  Even if
you found a compiler that would accept such an unethical sequence of code,
(two variables named "tail" -- wow!), you should not use it -- it would be
unportable, even to a different C compiler on the same machine/OS.  However,
I see how being able to forward reference structures, just as easily as we
can forward reference structure pointers today, could be appealing.

Joe Korty
uunet!modcomp!joe

gwyn@smoke.ARPA (Doug Gwyn ) (10/17/88)

In article <196@donk.UUCP> ajw@donk.UUCP (ajw) writes:
>Question is, is there a way to achieve this initialization within
>the letter of the law, leaving 'head' and 'tail' both static?

Do the following in sequence:
	declare "tail" to be a struct whatever (an incomplete type)
	declare what a "struct whatever" looks like
	initialize a declaration of "tail"
I don't have a copy of the standard at hand, but I think that's
supposed to work.

peter@ficc.uu.net (Peter da Silva) (10/17/88)

> Without the 'extern', the compiler can't initialize 'head'.  But with it, I
> get a 'non-standard extension' warning, although everything works just fine.

Would this work?

static struct whatever emptylist[2] = {
	{ &emptylist[1], NULL, NULL },
	{ NULL, &emptylist[0], NULL }
};
#define head &emptylist[0];
#define tail &emptylist[1];
-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation.
"Have you hugged  U  your wolf today?"            peter@ficc.uu.net

scs@athena.mit.edu (Steve Summit) (10/23/88)

In article <196@donk.UUCP> ajw@donk.UUCP (ajw) writes:
>Here's a fragment of code I find myself staring at glumly from
>time to time.  It sets up the nucleus of a 2-way list, into
>which extra malloc'd nodes will be inserted.

In general, I try not to have statically- and dynamically-
allocated elements in the same list, because of the possibility
of trying to free one of the statically-allocated ones.
Preventing this can require ugly special cases.

I usually use something like

	static struct whatever *head = NULL;
	static struct whatever *tail = NULL;

	insert_at_head(stuff)
	int stuff;
	{
	struct whatever *new;

	new = (struct whatever *)alloc(sizeof(struct whatever));

	new->eresting_stuff = stuff;
	new->next = head;
	head = new;
	new->prev = NULL;
	if(tail == NULL)
		tail = new;
	}

Note that head and tail are now pointers, not structures.  This
still requires one special case, to set tail initially, which is
one reason I don't like doubly-linked lists.  Complexity seems to
be O(n**2) with the number of links, so that doubly-linked lists
are four times as hard to get right as singly-linked ones.  (You
can insert at either the head or tail of a singly-linked list
without special casing the initial case, if you're clever.)

                                            Steve Summit
                                            scs@adam.pika.mit.edu