Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Missing braces around {0} initializer?!

3,171 views
Skip to first unread message

Tor Rustad

unread,
Feb 8, 2010, 1:13:41 PM2/8/10
to
I am puzzled by a warning, I get when using {0} as initializer. This
snippet demonstrate the warning:


struct tlv_item {
int tag;
int len;
char *val;
};

int main(void)
{
struct tlv_item tlv_1[10] = { 0 }; /* Why warning?! */
struct tlv_item tlv_2[10] = { {0,0,0} }; /* OK */

tlv_1[0].tag = tlv_2[0].tag = 1;

return 0;
}

$ gcc -Wall -ansi -pedantic clc_demo.c
clc_demo.c: In function �main�:
clc_demo.c:9: warning: missing braces around initializer
clc_demo.c:9: warning: (near initialization for �tlv_1[0]�)

$ gcc --version
gcc (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu4)


There was no warning with { {0,0,0} }, but I thought { 0 } was perfectly
conforming C as initializer above. Is this warning a compiler specific
thing which I can turn off somehow, or am I completely missing something
in Standard C here???

--
Tor <echo bwz...@wvtqvm.vw | tr i-za-h a-z>

Ben Pfaff

unread,
Feb 8, 2010, 1:19:33 PM2/8/10
to
Tor Rustad <bwz...@wvtqvm.vw> writes:
[...]

> There was no warning with { {0,0,0} }, but I thought { 0 } was
> perfectly conforming C as initializer above. Is this warning a
> compiler specific thing which I can turn off somehow, or am I
> completely missing something in Standard C here???

{ 0 } is perfectly conforming C, even in this case. GCC is
nevertheless warning about it because it thinks you probably made
a mistake. You can turn off the warning (GCC has an option for
that, I'm sure), or you can write out the initializer in full,
which will placate GCC, or you can ignore the warning.
--
"I should killfile you where you stand, worthless human." --Kaz

Seebs

unread,
Feb 8, 2010, 1:43:48 PM2/8/10
to
On 2010-02-08, Tor Rustad <bwz...@wvtqvm.vw> wrote:
> I am puzzled by a warning, I get when using {0} as initializer. This
> snippet demonstrate the warning:

> There was no warning with { {0,0,0} }, but I thought { 0 } was perfectly

> conforming C as initializer above. Is this warning a compiler specific
> thing which I can turn off somehow, or am I completely missing something
> in Standard C here???

I believe the answer is neither.

Rather, it's a *warning*. A helpful warning that, if you are initializing
an array of structures, it is clearer to put braces around the structure
initializers. Which it is. Most people won't be quite sure of the semantics
of something like

struct { int a, b, c; } foo[] = { 1, 2, 3, 4 };

and thus gcc warns you that you should probably have the right number of
levels of braces.

It's not saying your code violates the standard, just that your code has
characteristics which are very strongly suggestive that you have made a
typo.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Keith Thompson

unread,
Feb 8, 2010, 3:13:29 PM2/8/10
to
Seebs <usenet...@seebs.net> writes:
> On 2010-02-08, Tor Rustad <bwz...@wvtqvm.vw> wrote:
>> I am puzzled by a warning, I get when using {0} as initializer. This
>> snippet demonstrate the warning:
>
>> There was no warning with { {0,0,0} }, but I thought { 0 } was perfectly
>> conforming C as initializer above. Is this warning a compiler specific
>> thing which I can turn off somehow, or am I completely missing something
>> in Standard C here???
>
> I believe the answer is neither.
>
> Rather, it's a *warning*. A helpful warning that, if you are initializing
> an array of structures, it is clearer to put braces around the structure
> initializers. Which it is. Most people won't be quite sure of the semantics
> of something like
>
> struct { int a, b, c; } foo[] = { 1, 2, 3, 4 };
>
> and thus gcc warns you that you should probably have the right number of
> levels of braces.
>
> It's not saying your code violates the standard, just that your code has
> characteristics which are very strongly suggestive that you have made a
> typo.

Which are very strongly suggestive *to gcc*.

The initializer { 0 } sets all members of the initialized object to
zero. This is, or should be, a common C idiom. gcc just doesn't
recognize it.

gcc probably has an option to turn off the warning, but that option
will probably turn off some useful warnings as well. For example,
I definitly *want* a warning for


struct { int a, b, c; } foo[] = { 1, 2, 3, 4 };

but I don't want one for:
struct { int a, b, c; } foo[] = { 0 };
I don't think gcc distinguishes between those two cases.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Andrew Poelstra

unread,
Feb 8, 2010, 3:44:30 PM2/8/10
to
On 2010-02-08, Keith Thompson <ks...@mib.org> wrote:
>
> The initializer { 0 } sets all members of the initialized object to
> zero. This is, or should be, a common C idiom. gcc just doesn't
> recognize it.
>
> gcc probably has an option to turn off the warning, but that option
> will probably turn off some useful warnings as well. For example,
> I definitly *want* a warning for
> struct { int a, b, c; } foo[] = { 1, 2, 3, 4 };
> but I don't want one for:
> struct { int a, b, c; } foo[] = { 0 };
> I don't think gcc distinguishes between those two cases.
>

Even for

struct test {
int a;
int b;
int c;
}

int main(void) {
struct test t = { 0 };
return 0;
}

gcc warns me. And it's a particularly irritating warning because
it individually lists each struct member with a message that I am
"missing initialization".

So for some structs I get six or seven warning messages for every
single variable I initialize that way, so I then have to type out
struct test t = { 0, 0, 0 } like a goof or just not initialize it
at all (which gcc is perfectly fine with).

Tor Rustad

unread,
Feb 8, 2010, 3:46:47 PM2/8/10
to
Seebs wrote:
> On 2010-02-08, Tor Rustad <bwz...@wvtqvm.vw> wrote:
>> I am puzzled by a warning, I get when using {0} as initializer. This
>> snippet demonstrate the warning:
>
>> There was no warning with { {0,0,0} }, but I thought { 0 } was perfectly
>> conforming C as initializer above. Is this warning a compiler specific
>> thing which I can turn off somehow, or am I completely missing something
>> in Standard C here???
>
> I believe the answer is neither.
>
> Rather, it's a *warning*. A helpful warning that, if you are initializing
> an array of structures, it is clearer to put braces around the structure
> initializers. Which it is. Most people won't be quite sure of the semantics
> of something like
>
> struct { int a, b, c; } foo[] = { 1, 2, 3, 4 };
>
> and thus gcc warns you that you should probably have the right number of
> levels of braces.
>
> It's not saying your code violates the standard, just that your code has
> characteristics which are very strongly suggestive that you have made a
> typo.

I don't agree this was a useful warning, {0} had a crystal clear meaning
for me, until I saw that warning. If giving a warning for missing
braces, then {0} should have been an exception. Using { {0,0,0} }
instead, just add noise and using memset() even require an extra line.

After investigating the gcc man page, I finally (after zillion scrolls):

-Wmissing-braces
Warn if an aggregate or union initializer is not fully
bracketed. In the following example, the initializer for a is not fully
bracketed, but that for b is fully
bracketed.

int a[2][2] = { 0, 1, 2, 3 };
int b[2][2] = { { 0, 1 }, { 2, 3 } };

This warning is enabled by -Wall.

sooo... it appears we need to turn off -Wall, and that's not something I
will do.

Arrgh!

Andrew Poelstra

unread,
Feb 8, 2010, 3:48:20 PM2/8/10
to
On 2010-02-08, Andrew Poelstra <apoe...@localhost.localdomain> wrote:
> On 2010-02-08, Keith Thompson <ks...@mib.org> wrote:
>>
>> The initializer { 0 } sets all members of the initialized object to
>> zero. This is, or should be, a common C idiom. gcc just doesn't
>> recognize it.
>>
>> gcc probably has an option to turn off the warning, but that option
>> will probably turn off some useful warnings as well. For example,
>> I definitly *want* a warning for
>> struct { int a, b, c; } foo[] = { 1, 2, 3, 4 };
>> but I don't want one for:
>> struct { int a, b, c; } foo[] = { 0 };
>> I don't think gcc distinguishes between those two cases.
>>
>
> Even for
>
> struct test {
> int a;
> int b;
> int c;
> }

Missing a semicolon here.

>
> int main(void) {
> struct test t = { 0 };
> return 0;
> }
>
> gcc warns me. And it's a particularly irritating warning because
> it individually lists each struct member with a message that I am
> "missing initialization".
>

For that specific test program, it only gave me two lines of warnings
(plus an "unused variable" message). The first was "missing initializer"
and the second was "near initialization of something".

So perhaps I am thinking of g++ warning of every member.

Seebs

unread,
Feb 8, 2010, 3:50:47 PM2/8/10
to
On 2010-02-08, Keith Thompson <ks...@mib.org> wrote:
> The initializer { 0 } sets all members of the initialized object to
> zero. This is, or should be, a common C idiom. gcc just doesn't
> recognize it.

Hmm. I wouldn't have done that; I'd have done { { 0 } } to show that I was
aware that I was initializing an aggregate of aggregates.

I do agree that it might make sense to special-case the case where there's
exactly one initializer, and it's zero.

Ben Pfaff

unread,
Feb 8, 2010, 4:04:43 PM2/8/10
to
Andrew Poelstra <apoe...@localhost.localdomain> writes:

> Even for
>
> struct test {
> int a;
> int b;
> int c;
> }
>
> int main(void) {
> struct test t = { 0 };
> return 0;
> }
>
> gcc warns me. And it's a particularly irritating warning because
> it individually lists each struct member with a message that I am
> "missing initialization".

It's annoying.

In practice I often end up doing this:

struct test {
int a;
int b;
int c;

};

#define TEST_INITIALIZER { 0, 0, 0 }

int main(void) {
struct test t = TEST_INITIALIZER;
return 0;
}

--
"I'm not here to convince idiots not to be stupid.
They won't listen anyway."
--Dann Corbit

Kaz Kylheku

unread,
Feb 8, 2010, 4:14:23 PM2/8/10
to
On 2010-02-08, Ben Pfaff <b...@cs.stanford.edu> wrote:
> Andrew Poelstra <apoe...@localhost.localdomain> writes:
>
>> Even for
>>
>> struct test {
>> int a;
>> int b;
>> int c;
>> }
>>
>> int main(void) {
>> struct test t = { 0 };
>> return 0;
>> }
>>
>> gcc warns me. And it's a particularly irritating warning because
>> it individually lists each struct member with a message that I am
>> "missing initialization".
>
> It's annoying.

GCC is becoming annoying. The project has been taken over by twits.

Here is a gem: they decided that it's okay to generate deliberately broken
code when the function can detect at compile time that a function pointer
is being ``misused'' (cast to a different function type, and used to make
a call).

So I upgrade the compiler, rebuild an embedded Linux distro, boot it, and blam!
OpenSSH fails on key generation with a strange error, aborting on some kind
of illegal instruction.

After spending the time to trace the problem, I ended up patching this
goddamned idiocy out of the compiler.

Can you believe the reasoning? Let's break the code /deliberately/ just because
it invokes undefined behavior, but since we can't prove that it's reached,
let's translate the program successfully anyway. Let's give the distro
maintainer a clean build, so he can boot the system and go hunting for the
problem in the sea of shiny new executables.

Seebs

unread,
Feb 8, 2010, 4:16:58 PM2/8/10
to
On 2010-02-08, Kaz Kylheku <kkyl...@gmail.com> wrote:
> Here is a gem: they decided that it's okay to generate deliberately broken
> code when the function can detect at compile time that a function pointer
> is being ``misused'' (cast to a different function type, and used to make
> a call).

Specifically, when it's cast to a function type which does not match the
function *being called*.

And it should give you copious warnings when it triggers that, and it's
fixed as of OpenSSH 0.9.8f or so.

I seem to recall being told by someone closer to the code that the reason
is that otherwise the PPC compiler tended to blow up spectacularly trying
to optimize mismatched calls.

BTW, this sounds *eerily* familiar. When I encountered it, it involved
someone using a heavily-hacked OpenSSH 0.9.8 library, rather than the 0.9.8g
we shipped with that version of the product, because it had some specific
other bit of magic going on that was needed. I told the support people to
point the customer at the specific patches (I think that was 0.9.8f) to
openssh which fixed the calls to use the correct types.

But honestly, overall, I like that one. I am quite happy to have the compiler
throw out fierce warnings about something that is known to have a real chance
of blowing up in exciting ways, and to die cleanly rather than executing
garbage.

Keith Thompson

unread,
Feb 8, 2010, 4:24:54 PM2/8/10
to
Seebs <usenet...@seebs.net> writes:
> On 2010-02-08, Keith Thompson <ks...@mib.org> wrote:
>> The initializer { 0 } sets all members of the initialized object to
>> zero. This is, or should be, a common C idiom. gcc just doesn't
>> recognize it.
>
> Hmm. I wouldn't have done that; I'd have done { { 0 } } to show that I was
> aware that I was initializing an aggregate of aggregates.

Ok. Would you write { { { 0 } } } for an aggregate of aggregates of
aggregates? And so forth.

> I do agree that it might make sense to special-case the case where there's
> exactly one initializer, and it's zero.

Right. The point is that { 0 } means, regardless of the depth of the
object being initialized, that all members and elements are
initialized to zero (whatever "zero" means for the particular type).
The object can even be a scalar. And there's no other way to say
that.

On the other hand, { 0 } also means initializing a single-element
array or a single-member struct (or a union).

The rule that allows us to use { 0 } as a generic zero initializer is
C99 6.7.8p21:

If there are fewer initializers in a brace-enclosed list
than there are elements or members of an aggregate, or fewer
characters in a string literal used to initialize an array of
known size than there are elements in the array, the remainder
of the aggregate shall be initialized implicitly the same as
objects that have static storage duration.

Because the syntax requires at least one initializer between the
braces, you have to initialize the first element explicitly and leave
the rest, if any, to be initialized implicitly.

I'd like to see the syntax expanded to allow empty braces:

some_type obj = { };

with the same meaning as:

some_type obj = { 0 };

With the "{ }" syntax, you're unambiguously leaving all the members to
be initialized implicitly (and there'd be nothing for gcc to complain
about).

Seebs

unread,
Feb 8, 2010, 4:36:38 PM2/8/10
to
On 2010-02-08, Keith Thompson <ks...@mib.org> wrote:
> Seebs <usenet...@seebs.net> writes:
>> On 2010-02-08, Keith Thompson <ks...@mib.org> wrote:
>>> The initializer { 0 } sets all members of the initialized object to
>>> zero. This is, or should be, a common C idiom. gcc just doesn't
>>> recognize it.
>>
>> Hmm. I wouldn't have done that; I'd have done { { 0 } } to show that I was
>> aware that I was initializing an aggregate of aggregates.

> Ok. Would you write { { { 0 } } } for an aggregate of aggregates of
> aggregates? And so forth.

By default, yes. I think it's clearer.

> Because the syntax requires at least one initializer between the
> braces, you have to initialize the first element explicitly and leave
> the rest, if any, to be initialized implicitly.

Yup.

> With the "{ }" syntax, you're unambiguously leaving all the members to
> be initialized implicitly (and there'd be nothing for gcc to complain
> about).

Yes, that would be prettier.

Ben Bacarisse

unread,
Feb 8, 2010, 5:24:43 PM2/8/10
to
Keith Thompson <ks...@mib.org> writes:

> Seebs <usenet...@seebs.net> writes:
<snip>


>> I do agree that it might make sense to special-case the case where there's
>> exactly one initializer, and it's zero.
>
> Right. The point is that { 0 } means, regardless of the depth of the
> object being initialized, that all members and elements are
> initialized to zero (whatever "zero" means for the particular type).
> The object can even be a scalar. And there's no other way to say
> that.
>
> On the other hand, { 0 } also means initializing a single-element
> array or a single-member struct (or a union).

... or single scalar.

> The rule that allows us to use { 0 } as a generic zero initializer is
> C99 6.7.8p21:
>
> If there are fewer initializers in a brace-enclosed list
> than there are elements or members of an aggregate, or fewer
> characters in a string literal used to initialize an array of
> known size than there are elements in the array, the remainder
> of the aggregate shall be initialized implicitly the same as
> objects that have static storage duration.

[just for completeness...] together with p11 in the same section:

The initializer for a scalar shall be a single expression,
optionally enclosed in braces. [....]

<snip>


> I'd like to see the syntax expanded to allow empty braces:
>
> some_type obj = { };
>
> with the same meaning as:
>
> some_type obj = { 0 };

Nice idea.

<snip>
--
Ben.

Ben Bacarisse

unread,
Feb 8, 2010, 5:37:51 PM2/8/10
to
Tor Rustad <bwz...@wvtqvm.vw> writes:
<snip>

> After investigating the gcc man page, I finally (after zillion scrolls):
>
> -Wmissing-braces
> Warn if an aggregate or union initializer is not fully
> bracketed. In the following example, the initializer for a is not
> fully bracketed, but that for b is fully
> bracketed.
>
> int a[2][2] = { 0, 1, 2, 3 };
> int b[2][2] = { { 0, 1 }, { 2, 3 } };
>
> This warning is enabled by -Wall.
>
>
>
> sooo... it appears we need to turn off -Wall, and that's not something
> I will do.

You need only turn off:

-Wno-missing-braces -Wno-missing-field-initializers

and {0} becomes a silent universal initializer. You will still be
warned about excess initializers but, sadly, this:

int primes[5] = { 2, 3, 5, 7 };

will be silent too. I can live with that.

--
Ben.

Richard Heathfield

unread,
Feb 8, 2010, 6:31:51 PM2/8/10
to
Tor Rustad wrote:
> I am puzzled by a warning, I get when using {0} as initializer.

That warning has irritated me for *years*.

I really wish gcc's warnings were independently configurable. (Perhaps
they are, but that's strictly a matter for a gcc group.)

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within

Tor Rustad

unread,
Feb 8, 2010, 6:50:19 PM2/8/10
to

Ahh.. that did the trick, thanks! I just needed to add
-Wno-missing-braces, and then

gcc -Wall -ansi -pedantic -Wno-missing-braces clc_demo.c

produced no warnings. Using "-Wall -ansi -pedantic" give no warning
anyway for

int primes[5] = { 2, 3, 5, 7 };

so nothing lost in that case.

Phil Carmody

unread,
Feb 8, 2010, 6:54:37 PM2/8/10
to
Keith Thompson <ks...@mib.org> writes:
> Seebs <usenet...@seebs.net> writes:
>> On 2010-02-08, Tor Rustad <bwz...@wvtqvm.vw> wrote:
>>> I am puzzled by a warning, I get when using {0} as initializer. This
>>> snippet demonstrate the warning:
>>
>>> There was no warning with { {0,0,0} }, but I thought { 0 } was perfectly
>>> conforming C as initializer above. Is this warning a compiler specific
>>> thing which I can turn off somehow, or am I completely missing something
>>> in Standard C here???
>>
>> I believe the answer is neither.
>>
>> Rather, it's a *warning*. A helpful warning that, if you are initializing
>> an array of structures, it is clearer to put braces around the structure
>> initializers. Which it is. Most people won't be quite sure of the semantics
>> of something like
>>
>> struct { int a, b, c; } foo[] = { 1, 2, 3, 4 };
>>
>> and thus gcc warns you that you should probably have the right number of
>> levels of braces.
>>
>> It's not saying your code violates the standard, just that your code has
>> characteristics which are very strongly suggestive that you have made a
>> typo.
>
> Which are very strongly suggestive *to gcc*.
>
> The initializer { 0 } sets all members of the initialized object to
> zero. This is, or should be, a common C idiom. gcc just doesn't
> recognize it.

Please provide proof that it doesn't recognise it. Please be more
detailed than the above - precisely which bit of the construct do
you think it is unable to cope with? From my perspective, it looks
as if it understands the construct and the legality, and typical use,
of same, perfectly.

Phil
--
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1

Phil Carmody

unread,
Feb 8, 2010, 6:57:39 PM2/8/10
to
Kaz Kylheku <kkyl...@gmail.com> writes:
> Can you believe the reasoning? Let's break the code /deliberately/ just because
> it invokes undefined behavior

If it's UB, it's already broken, I don't think you can blame
the compiler for shoving that in your face so abruptly. Perhaps
you should thank it, instead?

Tor Rustad

unread,
Feb 8, 2010, 7:04:53 PM2/8/10
to
Richard Heathfield wrote:
> Tor Rustad wrote:
>> I am puzzled by a warning, I get when using {0} as initializer.
>
> That warning has irritated me for *years*.
>
> I really wish gcc's warnings were independently configurable.

Like e.g.

-Wno-missing-braces

?

> (Perhaps they are, but that's strictly a matter for a gcc group.)

Yeah, yeah.. nothing has changed here I see. *lol*

Ben Bacarisse

unread,
Feb 8, 2010, 7:05:40 PM2/8/10
to
Richard Heathfield <r...@see.sig.invalid> writes:

> Tor Rustad wrote:
>> I am puzzled by a warning, I get when using {0} as initializer.
>
> That warning has irritated me for *years*.
>
> I really wish gcc's warnings were independently configurable. (Perhaps
> they are, but that's strictly a matter for a gcc group.)

It's the word "strictly" that prompts me to post.

You accept topicality drift within a thread -- into the merits of
Norman Wisdom's slapstick for example -- but you seem to be suggesting
that how one might configure gcc's warnings is beyond the pale.

--
Ben.

Richard

unread,
Feb 8, 2010, 7:20:51 PM2/8/10
to
Richard Heathfield <r...@see.sig.invalid> writes:

> Tor Rustad wrote:
>> I am puzzled by a warning, I get when using {0} as initializer.
>
> That warning has irritated me for *years*.
>
> I really wish gcc's warnings were independently configurable. (Perhaps
> they are, but that's strictly a matter for a gcc group.)
>
> <snip>

Huh? were you not preening about how you personally welcome more
topicality only recently? And I can hardly "C" how discussing one of the
most popular C compilers in the world in a C programming newsgroup is
off topic. Its warnings etc ARE rather linked to the standard ....

--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c

Keith Thompson

unread,
Feb 8, 2010, 8:10:41 PM2/8/10
to

Hmm. I really thought I was sufficiently clear.

gcc, like any conforming C compiler, certainly recognizes the
initializer { 0 } and correctly handles its syntax and semantics.
What I meant is that it doesn't recognize it *as an idiom* for
"recursively initialize this object and all its sub-members and
sub-elements to zero".

Consider the following translation unit:

struct s { int x; int y; int z; };
struct s s1 = { 0 };
struct s s2 = { 0, 0 };

With "-Wmissing-field-initializers" or equivalent, gcc warns about
both initializers. With "-Wno-missing-field-initializers", gcc
doesn't warn about either of them.

What I would like is a way to make gcc, or whatever compiler I happen
to be using, to warn about the initialization of s2 (because it's
missing an initializer for z), but not about the initialization
of s1 (because it's using the "{ 0 }" idiom, and I *deliberately*
omitted explicit initializers for most of the members).

One possible drawback is that if I write "{ 0 }", I might really
have meant that the object has exactly one member or element rather
than that I don't want to specify how many it has.

What I'd like even better is a change to the language so that "{ }"
is equivalent to what "{ 0 }" currently means, but I can expect a
compiler not to warn me about it.

I have another idea, but it would break tons of existing code, so it's
unlikely ever to make it into the language. By default, require
explicit initializers for all subobjects. Allow "..." to indicate
that the current subobject and everything following it is implicitly
zero. Thus:

struct s s1 = { 0 }; /* constraint violation */
struct s s2 = { 42, ... }; /* x = 42, y = 0, z = 0 */
struct s s3 = { ... }; /* initialize all members to 0 */
struct s s4 = { 1, 2, 3, ... }; /* probably ok */

There would be a lot of details to work out; since it would break
existing code, I won't bother.

Andrew Poelstra

unread,
Feb 8, 2010, 8:35:13 PM2/8/10
to
On 2010-02-08, Phil Carmody <thefatphi...@yahoo.co.uk> wrote:
> Kaz Kylheku <kkyl...@gmail.com> writes:
>> Can you believe the reasoning? Let's break the code /deliberately/ just because
>> it invokes undefined behavior
>
> If it's UB, it's already broken, I don't think you can blame
> the compiler for shoving that in your face so abruptly. Perhaps
> you should thank it, instead?
>
> Phil

I think his point was that it /didn't/ give him an abrupt
warning. It went out of its way to interpret a nonsensical
construct as nonsense rather than issuing a warning.

So it caused a runtime crash.

At least, I think that's what happened. I wasn't quite
clear on his original post either.

William Ahern

unread,
Feb 8, 2010, 9:15:23 PM2/8/10
to
Andrew Poelstra <apoe...@localhost.localdomain> wrote:
<snip>

> Even for
>
> struct test {
> int a;
> int b;
> int c;
> }
>
> int main(void) {
> struct test t = { 0 };
> return 0;
> }
>
> gcc warns me. And it's a particularly irritating warning because
> it individually lists each struct member with a message that I am
> "missing initialization".
>

What version of GCC are you using? I can't replicate that warning with any
of 3.3.5 (OpenBSD), 4.0.1 (Apple), 4.2.1 (Apple), 4.2.4 (Ubuntu), 4.3.3
(GCC), 4.3.4 (Ubuntu), or 4.4.1 (Ubuntu). I've tried -Wall with every
combination of -ansi -pedantic xor -std=c99, and -O2 xor no optimization.

Occasionaly I do get a warning about missing initializers in compound
literals, seemingly without rhyme nor reason. But I never pursued it beyond
checking the code for bugs. Now you've piqued my interest.

Here's the code I used

struct test {
int a, b, c;
};

int main(void) {
struct test t = { 0 };

return t.c;
}

Separately, I tried some combos with `struct test { int a; int b, c; };'.
No difference.

Ben Bacarisse

unread,
Feb 8, 2010, 9:46:24 PM2/8/10
to
William Ahern <wil...@wilbur.25thandClement.com> writes:

> Andrew Poelstra <apoe...@localhost.localdomain> wrote:
> <snip>
>> Even for
>>
>> struct test {
>> int a;
>> int b;
>> int c;
>> }
>>
>> int main(void) {
>> struct test t = { 0 };
>> return 0;
>> }
>>
>> gcc warns me. And it's a particularly irritating warning because
>> it individually lists each struct member with a message that I am
>> "missing initialization".
>
> What version of GCC are you using? I can't replicate that warning with any
> of 3.3.5 (OpenBSD), 4.0.1 (Apple), 4.2.1 (Apple), 4.2.4 (Ubuntu), 4.3.3
> (GCC), 4.3.4 (Ubuntu), or 4.4.1 (Ubuntu). I've tried -Wall with every
> combination of -ansi -pedantic xor -std=c99, and -O2 xor no
> optimization.

It's turned on with -Wextra.

<snip>
--
Ben.

Seebs

unread,
Feb 8, 2010, 10:00:02 PM2/8/10
to
On 2010-02-09, Andrew Poelstra <apoe...@localhost.localdomain> wrote:
> I think his point was that it /didn't/ give him an abrupt
> warning. It went out of its way to interpret a nonsensical
> construct as nonsense rather than issuing a warning.

I am pretty sure that ALWAYS generates a warning. What it doesn't do
is abort compilation.

William Ahern

unread,
Feb 8, 2010, 10:34:37 PM2/8/10
to
Ben Bacarisse <ben.u...@bsb.me.uk> wrote:
<snip>

> It's turned on with -Wextra.

Ah, thank you.

This C99 named initialization construct works w/o any warning:

struct test t = { .a = 0 };

I want to say that the standard explicitly says that every other member is
implicitly zero initialized in this case, but that's just from my poor
memory.

Richard Heathfield

unread,
Feb 9, 2010, 2:32:11 AM2/9/10
to
Tor Rustad wrote:
> Richard Heathfield wrote:
>> Tor Rustad wrote:
>>> I am puzzled by a warning, I get when using {0} as initializer.
>>
>> That warning has irritated me for *years*.
>>
>> I really wish gcc's warnings were independently configurable.
>
> Like e.g.
>
> -Wno-missing-braces
>
> ?

Well well well, there's a thing. :-)

Richard Heathfield

unread,
Feb 9, 2010, 2:38:54 AM2/9/10
to

No sir, I am suggesting that for me to launch an entire subthread by
seeking advice in this group on configuring gcc's warnings would be most
hypocritical indeed. By comparison, a one-line indulgence of someone
else's topic drift is of little consequence (or at least would have
been, had it not prompted this response).

Phil Carmody

unread,
Feb 9, 2010, 4:03:40 AM2/9/10
to

Hmm. I really thought I was sufficiently clear. The above is no
proof that it's not recognised as an idiom for the above. Just
because it's recognised as an idiom doesn't mean the compiler can't
throw up warnings about it. Calling something an idiom doesn't
magically make everything that looks like it safe and not worth
warning about. Common mistakes can be idiomatic of a language too.

> Consider the following translation unit:
>
> struct s { int x; int y; int z; };
> struct s s1 = { 0 };
> struct s s2 = { 0, 0 };
>
> With "-Wmissing-field-initializers" or equivalent, gcc warns about
> both initializers. With "-Wno-missing-field-initializers", gcc
> doesn't warn about either of them.
>
> What I would like is a way to make gcc, or whatever compiler I happen
> to be using, to warn about the initialization of s2 (because it's
> missing an initializer for z), but not about the initialization
> of s1 (because it's using the "{ 0 }" idiom, and I *deliberately*
> omitted explicit initializers for most of the members).
>
> One possible drawback is that if I write "{ 0 }", I might really
> have meant that the object has exactly one member or element rather
> than that I don't want to specify how many it has.

Exactly. Treating elision to denote intent is dangerous. Sufficiently
dangerous for gcc to consider it worth a warning with most common
invocations.

> What I'd like even better is a change to the language so that "{ }"
> is equivalent to what "{ 0 }" currently means, but I can expect a
> compiler not to warn me about it.

I approve of that, certainly.

> I have another idea, but it would break tons of existing code, so it's
> unlikely ever to make it into the language. By default, require
> explicit initializers for all subobjects. Allow "..." to indicate
> that the current subobject and everything following it is implicitly
> zero. Thus:
>
> struct s s1 = { 0 }; /* constraint violation */
> struct s s2 = { 42, ... }; /* x = 42, y = 0, z = 0 */
> struct s s3 = { ... }; /* initialize all members to 0 */
> struct s s4 = { 1, 2, 3, ... }; /* probably ok */
>
> There would be a lot of details to work out; since it would break
> existing code, I won't bother.

I approve of an explicit '...' to represent an explicit request
(to initialise all further subobjects to 0) too. Only the orthogonal
addition of the requirement for other initialisations to be fully
explicit causes breakage.

Ben Bacarisse

unread,
Feb 9, 2010, 8:34:04 AM2/9/10
to
William Ahern <wil...@wilbur.25thandClement.com> writes:

Yes they are. 6.7.8 p19:

The initialization shall occur in initializer list order, each
initializer provided for a particular subobject overriding any
previously listed initializer for the same subobject; all subobjects
that are not initialized explicitly shall be initialized implicitly


the same as objects that have static storage duration.

--
Ben.

Keith Thompson

unread,
Feb 9, 2010, 12:44:26 PM2/9/10
to
Phil Carmody <thefatphi...@yahoo.co.uk> writes:
> Keith Thompson <ks...@mib.org> writes:
>> Phil Carmody <thefatphi...@yahoo.co.uk> writes:
>>> Keith Thompson <ks...@mib.org> writes:
[...]

>>>> The initializer { 0 } sets all members of the initialized object to
>>>> zero. This is, or should be, a common C idiom. gcc just doesn't
>>>> recognize it.
>>>
>>> Please provide proof that it doesn't recognise it. Please be more
>>> detailed than the above - precisely which bit of the construct do
>>> you think it is unable to cope with? From my perspective, it looks
>>> as if it understands the construct and the legality, and typical use,
>>> of same, perfectly.
>>
>> Hmm. I really thought I was sufficiently clear.
>>
>> gcc, like any conforming C compiler, certainly recognizes the
>> initializer { 0 } and correctly handles its syntax and semantics.
>> What I meant is that it doesn't recognize it *as an idiom* for
>> "recursively initialize this object and all its sub-members and
>> sub-elements to zero".
>
> Hmm. I really thought I was sufficiently clear.

No, I thought you were missing my point, deliberately or otherwise.

> The above is no
> proof that it's not recognised as an idiom for the above. Just
> because it's recognised as an idiom doesn't mean the compiler can't
> throw up warnings about it. Calling something an idiom doesn't
> magically make everything that looks like it safe and not worth
> warning about. Common mistakes can be idiomatic of a language too.

If gcc recognizes { 0 } as an idiom, it doesn't appear to do anything
with the information. As far as I can tell, it doesn't make any
distinction at all between { 0 } and any other initializer that
leaves some sub-objects to take implicit 0 values. It doesn't treat
{ 0 } as any kind of special case. Perhaps you see some meaningful
distinction here. I don't.

>> Consider the following translation unit:
>>
>> struct s { int x; int y; int z; };
>> struct s s1 = { 0 };
>> struct s s2 = { 0, 0 };
>>
>> With "-Wmissing-field-initializers" or equivalent, gcc warns about
>> both initializers. With "-Wno-missing-field-initializers", gcc
>> doesn't warn about either of them.
>>
>> What I would like is a way to make gcc, or whatever compiler I happen
>> to be using, to warn about the initialization of s2 (because it's
>> missing an initializer for z), but not about the initialization
>> of s1 (because it's using the "{ 0 }" idiom, and I *deliberately*
>> omitted explicit initializers for most of the members).
>>
>> One possible drawback is that if I write "{ 0 }", I might really
>> have meant that the object has exactly one member or element rather
>> than that I don't want to specify how many it has.
>
> Exactly. Treating elision to denote intent is dangerous. Sufficiently
> dangerous for gcc to consider it worth a warning with most common
> invocations.

Which may well be why gcc doesn't recognize { 0 } as an idiom (i.e.,
treat it as a special case that doesn't require a warning).

Nevertheless, I think that the risk of failing to warn about
{ 0 } when it's incorrect is outweighed by the benefit of dropping
the warning in the majority of cases where it's correct.

Then again, there's another way to do this, though it requires
an extra declaration:

const static struct s struct_s_zero;
struct s s1 = struct_s_zero;

>> What I'd like even better is a change to the language so that "{ }"
>> is equivalent to what "{ 0 }" currently means, but I can expect a
>> compiler not to warn me about it.
>
> I approve of that, certainly.
>
>> I have another idea, but it would break tons of existing code, so it's
>> unlikely ever to make it into the language. By default, require
>> explicit initializers for all subobjects. Allow "..." to indicate
>> that the current subobject and everything following it is implicitly
>> zero. Thus:
>>
>> struct s s1 = { 0 }; /* constraint violation */
>> struct s s2 = { 42, ... }; /* x = 42, y = 0, z = 0 */
>> struct s s3 = { ... }; /* initialize all members to 0 */
>> struct s s4 = { 1, 2, 3, ... }; /* probably ok */
>>
>> There would be a lot of details to work out; since it would break
>> existing code, I won't bother.
>
> I approve of an explicit '...' to represent an explicit request
> (to initialise all further subobjects to 0) too. Only the orthogonal
> addition of the requirement for other initialisations to be fully
> explicit causes breakage.

The problem with that variation of the idea is that, assuming "..."
is permitted when there are no remaining subobjects, it doesn't
mean anything. Any initializer with ", ..." still means exactly
the same thing if you delete the ", ...". A compiler could use the
presence of ", ..." to decide not to issue a warning (in a context
that doesn't require a diagnostic anyway), but I doubt that the
committee would accept that as a good enough reason to add a new
feature to the language. A comment would serve the same purpose.

If the ", ..." is permitted only when there are additional
subobjects, so that my example


struct s s4 = { 1, 2, 3, ... };

is a constraint violation, it might be a useful feature. But then you
couldn't use { 0, ... } in all cases.

Malcolm McLean

unread,
Feb 9, 2010, 12:53:30 PM2/9/10
to
On Feb 9, 2:05 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>
> You accept topicality drift within a thread -- into the merits of
> Norman Wisdom's slapstick for example -- but you seem to be suggesting
> that how one might configure gcc's warnings is beyond the pale.
>
>
There's a difference between topic drift (from C's logical operators
to binary numbers to the possibility of building a base phi computer
to Fibbonacci series generally to connections between Fibbonaci series
and the Mandelbrot set to computer graphics to X-windows bad graphics
capabilities to gcc warnings) and starting off a thread on gcc
warnings.

Ike Naar

unread,
Feb 9, 2010, 6:05:40 PM2/9/10
to
In article <lnk4umi...@nuthaus.mib.org>,

Keith Thompson <ks...@mib.org> wrote:
>Then again, there's another way to do this, though it requires
>an extra declaration:
>
> const static struct s struct_s_zero;
> struct s s1 = struct_s_zero;

This is good for another warning :-(
a.c:1: warning: `static' is not at beginning of declaration

Peter Nilsson

unread,
Feb 9, 2010, 11:01:32 PM2/9/10
to
i...@localhost.claranet.nl (Ike Naar) wrote:

> Keith Thompson  <ks...@mib.org> wrote:
> >    const static struct s struct_s_zero;
> >    struct s s1 = struct_s_zero;
>
> This is good for another warning :-(
> a.c:1: warning: `static' is not at beginning of declaration

It's a constraint violation in fact, since storage class
specifiers must precede type qualifiers in declarations.

--
Peter

Phil Carmody

unread,
Feb 10, 2010, 5:01:23 AM2/10/10
to

It doesn't need to be. I like warnings from compilers to keep
tabs on some style issues, but that looks pointlessly pedantic.

Ben Bacarisse

unread,
Feb 10, 2010, 7:02:45 AM2/10/10
to
Peter Nilsson <ai...@acay.com.au> writes:

I can't see where. Can you give a reference? The standard includes
(in footnote 315) the following example:

const static double one_third = 1.0/3.0;

which suggests otherwise.

--
Ben.

Keith Thompson

unread,
Feb 10, 2010, 11:14:13 AM2/10/10
to
Phil Carmody <thefatphi...@yahoo.co.uk> writes:
> i...@localhost.claranet.nl (Ike Naar) writes:
>> In article <lnk4umi...@nuthaus.mib.org>,
>> Keith Thompson <ks...@mib.org> wrote:
>>>Then again, there's another way to do this, though it requires
>>>an extra declaration:
>>>
>>> const static struct s struct_s_zero;
>>> struct s s1 = struct_s_zero;
>>
>> This is good for another warning :-(
>> a.c:1: warning: `static' is not at beginning of declaration
>
> It doesn't need to be. I like warnings from compilers to keep
> tabs on some style issues, but that looks pointlessly pedantic.

C99 6.11.5:

The placement of a storage-class specifier other than at the
beginning of the declaration specifiers in a declaration is an
obsolescent feature.

A warning seems reasonable to me. (And I should have compiled the
code, with maximum warnings, before posting it.)

Peter Nilsson

unread,
Feb 10, 2010, 4:36:55 PM2/10/10
to
On Feb 10, 11:02 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> Peter Nilsson <ai...@acay.com.au> writes:
> > ... storage class specifiers must precede type qualifiers

> > in declarations.
>
> I can't see where.  Can you give a reference?

It's been marked obsolescent since C89. I was under the mistaken
impression that it actually had been removed.

>  The standard includes
> (in footnote 315) the following example:
>
>   const static double one_third = 1.0/3.0;
>
> which suggests otherwise.

Which I see is in N1425 as footnote 340. So it's obsolescent,
but not discouraged!

--
Peter

Ben Bacarisse

unread,
Feb 10, 2010, 6:05:16 PM2/10/10
to
Peter Nilsson <ai...@acay.com.au> writes:

> On Feb 10, 11:02 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> Peter Nilsson <ai...@acay.com.au> writes:
>> > ... storage class specifiers must precede type qualifiers
>> > in declarations.
>>
>> I can't see where.  Can you give a reference?
>
> It's been marked obsolescent since C89. I was under the mistaken
> impression that it actually had been removed.

And I did not know it was marked as obsolescent, so it was useful post
all around.

>>  The standard includes
>> (in footnote 315) the following example:
>>
>>   const static double one_third = 1.0/3.0;
>>
>> which suggests otherwise.
>
> Which I see is in N1425 as footnote 340. So it's obsolescent,
> but not discouraged!

Another example was posted recently from the rationale. It's almost
being encouraged!

--
Ben.

Phil Carmody

unread,
Feb 11, 2010, 5:35:16 AM2/11/10
to
Keith Thompson <ks...@mib.org> writes:
> Phil Carmody <thefatphi...@yahoo.co.uk> writes:
>> i...@localhost.claranet.nl (Ike Naar) writes:
>>> In article <lnk4umi...@nuthaus.mib.org>,
>>> Keith Thompson <ks...@mib.org> wrote:
>>>>Then again, there's another way to do this, though it requires
>>>>an extra declaration:
>>>>
>>>> const static struct s struct_s_zero;
>>>> struct s s1 = struct_s_zero;
>>>
>>> This is good for another warning :-(
>>> a.c:1: warning: `static' is not at beginning of declaration
>>
>> It doesn't need to be. I like warnings from compilers to keep
>> tabs on some style issues, but that looks pointlessly pedantic.
>
> C99 6.11.5:
>
> The placement of a storage-class specifier other than at the
> beginning of the declaration specifiers in a declaration is an
> obsolescent feature.
>
> A warning seems reasonable to me. (And I should have compiled the
> code, with maximum warnings, before posting it.)

Ah, the 'future' section, indeed. (Aside - it seems odd that that
section is normative, given that it refers to nothing tangible.)
Thanks for that anyway.

Azazel

unread,
Feb 13, 2010, 4:24:29 PM2/13/10
to
On 2010-02-08, Ben Pfaff <b...@cs.stanford.edu> wrote:

> Andrew Poelstra <apoe...@localhost.localdomain> writes:
>
>> Even for
>>
>> struct test {
>> int a;
>> int b;
>> int c;
>> }
>>
>> int main(void) {
>> struct test t = { 0 };
>> return 0;
>> }
>>
>> gcc warns me. And it's a particularly irritating warning because
>> it individually lists each struct member with a message that I am
>> "missing initialization".
>
> It's annoying.
>
> In practice I often end up doing this:

>
> struct test {
> int a;
> int b;
> int c;
> };
>
> #define TEST_INITIALIZER { 0, 0, 0 }
>
> int main(void) {
> struct test t = TEST_INITIALIZER;
> return 0;
> }

Using a file-scope static variable one can leave the compiler to sort it
out:

struct test
{
int a;
int b;
int c;

};

static const struct test TEST_INITIALIZER;

int
main (void)
{
struct test t = TEST_INITIALIZER;
return 0;
}

--
Az.

www: http://www.azazel.net/
pgp: http://www.azazel.net/~azazel/az_key.asc

0 new messages