comma at end of initializer allowed?

S

Serve Laurijssen

Is code like the following allowed? I am talking about the comma after the
last function in the initializer.

void f(void) {puts("f");}
void g(void) {puts("g");}

struct Funcs { void (*f[])(void); };

struct Funcs funcs =
{
f,
g,
};

I ask because it makes generating code a lot easier.
 
S

Severian

Is code like the following allowed? I am talking about the comma after the
last function in the initializer.

void f(void) {puts("f");}
void g(void) {puts("g");}

struct Funcs { void (*f[])(void); };

struct Funcs funcs =
{
f,
g,
};

I ask because it makes generating code a lot easier.

I believe it is (and IIRC the rationale was for precisely this
reason). But is it really a big deal to avoid a single if statement,
?: or return buf+x?

I've written lots of code that generates comma-separated lists (and
,\n separated lines, and FF separated pages) that managed to handle
the issue with a few bytes of simple code.
 
I

Ike Naar

: On Tue, 20 Apr 2004 09:10:49 +0200, "Serve Laurijssen"
:>Is code like the following allowed? I am talking about the comma after the
:>last function in the initializer.
:>
:>void f(void) {puts("f");}
:>void g(void) {puts("g");}
:>
:>struct Funcs { void (*f[])(void); };
:>
:>struct Funcs funcs =
:>{
:>f,
:>g,
:>};
:>
:>I ask because it makes generating code a lot easier.
:>

Alternatively, you can put a dummy element or a null pointer at the end,
e.g.

struct Funcs funcs =
{
f,
g,
NULL
}
 
S

Severian

: On Tue, 20 Apr 2004 09:10:49 +0200, "Serve Laurijssen"
:>Is code like the following allowed? I am talking about the comma after the
:>last function in the initializer.
:>
:>void f(void) {puts("f");}
:>void g(void) {puts("g");}
:>
:>struct Funcs { void (*f[])(void); };
:>
:>struct Funcs funcs =

I didn't notice late last night, but this obviously needs to be

struct Funcs funcs[] =
:>{
:>f,
:>g,
:>};
:>
:>I ask because it makes generating code a lot easier.
:>

Alternatively, you can put a dummy element or a null pointer at the end,
e.g.

struct Funcs funcs =
{
f,
g,
NULL
}

Yes, this is sometimes the appropriate thing to do, if the processing
code is written that way, and if the wasted storage is insignificant.

Sometimes you don't have control over it; a lot of my code to generate
lists is for use in other ways (CSV files, SQL queries, etc.), which
do not allow for excess commas or 'NULL.' It's best to learn good ways
to generate such lists without depending on historical C compiler
allowances. The overhead is so minimal that it can almost always be
ignored.
 
D

Dan Pop

In said:
do not allow for excess commas or 'NULL.' It's best to learn good ways
to generate such lists without depending on historical C compiler
allowances.

It's not historical, it's a C89 invention.

Dan
 
S

Severian

It's not historical, it's a C89 invention.

I may very well be mistaken [1989 was a long time ago on my brief
timeline (b. 1961), I've written millions of lines of code, and I'm
unlikely to spend any time researching the issue], but I remember that
this became part of the standard because many extant C compilers
already accepted the syntax.

I remember it as more a concession to YACC (or some other code
generator) output than anything else.

I know that VAX C (not a great example of a C compiler, but DEC was a
powerful member of the committee) and several PC C compilers handled
it as it was standardized.

(I will have no problem saying "Oops, my bad" if necessary, because
this is totally from memory and I have no emotional attachment to it.)
 
C

Chris Torek

(Dan is rarely wrong, but I have some vague memory of Dennis'
compilers accepting trailing commas in initializers.)

I remember it as more a concession to YACC (or some other code
generator) output than anything else.

This seems unlikely, because PCC (the first YACC-based C compiler)
accepted trailing commas in initializers but not in "enum"s. It
is easy enough to write one's grammar either way.

We might even note that trailing commas were still not valid in
"enum"s in C89 (they finally are, in C99).
 
D

Dan Pop

In said:
It's not historical, it's a C89 invention.

I may very well be mistaken [1989 was a long time ago on my brief
timeline (b. 1961), I've written millions of lines of code, and I'm
unlikely to spend any time researching the issue], but I remember that
this became part of the standard because many extant C compilers
already accepted the syntax.

It turns out I was wrong: it was a standard C feature since "day one",
i.e. since K&R1 was printed. Retained by the standardisation committee
because "it provides flexibility in adding or deleting members from
an initializer list, and simplifies machine generation of such lists".

Dan
 
A

Arthur J. O'Dwyer

Ike Naar said:
:> Is code like the following allowed? I am talking about the comma
:> after the last function in the initializer.
:>
:> void f(void) {puts("f");}
:> void g(void) {puts("g");}
:>
:> struct Funcs { void (*f[])(void); };
:>
:> struct Funcs funcs =

I didn't notice late last night, but this obviously needs to be

struct Funcs funcs[] =

No, it doesn't. Look closely at the typedef for 'Funcs'. :)
I don't follow C99 weird-array syntax closely enough to tell if
that typedef is legal, but GNU C accepts it with a warning. (This
means it's probably not standard C. Add a '2' inside the '[]' in
the typedef if you want to compile it.)

*This*, however, definitely needs to be

{ {f,g,} };

(two pairs of braces). One pair for the struct and an inner pair for
the initializer for the array member.
Yes, this is sometimes the appropriate thing to do, if the processing
code is written that way, and if the wasted storage is insignificant.

Just in case you didn't see it (I can't tell from your response),
I think Ike's point was that if your code-generator dumps a bunch
of

xxx,

followed by the string

NULL
}

then you don't have to worry about the extra trailing comma. The
NULL itself can be ignored --- /if the processing code is written
that way/, of course. ;-)
Sometimes you don't have control over it; a lot of my code to generate
lists is for use in other ways (CSV files, SQL queries, etc.), which
do not allow for excess commas or 'NULL.' It's best to learn good ways
to generate such lists without depending on historical C compiler
allowances. The overhead is so minimal that it can almost always be
ignored.

Modulo Dan's comments about "historical" (hey, 1989 sounds pretty
historical to *me*! ;) , you're right.

-Arthur
 
C

Chris Dollin

Serve said:
Is code like the following allowed? I am talking about the comma after the
last function in the initializer.

void f(void) {puts("f");}
void g(void) {puts("g");}

struct Funcs { void (*f[])(void); };

struct Funcs funcs =
{
f,
g,
};

I ask because it makes generating code a lot easier.

Hardly. *Slightly* easier, I'd buy. My standard idiom for this thinks
of the separator as being *before* each element, not *after*, with
a special case for the first element, and looks like

separator = nothing or a space or other I'm-not-here
for each item x do
output the separator
output x
separator = the non-trivial separator
endfor
 
G

glen herrmannsfeldt

Chris said:
Serve Laurijssen wrote:
(snip)
Hardly. *Slightly* easier, I'd buy.

However slight, it is legal in C and Java.

If is helpful if using #ifdef within the initializer,
when you don't know which items will be used.

Also, for initializers generated by a program, though in
that case it isn't so hard to fix up the last item.

-- glen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top