|
|||
|
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 bwzcab@wvtqvm.vw | tr i-za-h a-z> |
|
|
||||
|
||||
|
|
|
|||
|
Tor Rustad <bwzcab@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 |
|
|||
|
On 2010-02-08, Tor Rustad <bwzcab@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-nospam@seebs.net http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated! |
|
|||
|
Seebs <usenet-nospam@seebs.net> writes:
> On 2010-02-08, Tor Rustad <bwzcab@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) kst-u@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" |
|
|||
|
On 2010-02-08, Keith Thompson <kst-u@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). |
|
|||
|
Seebs wrote:
> On 2010-02-08, Tor Rustad <bwzcab@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! -- Tor <echo bwzcab@wvtqvm.vw | tr i-za-h a-z> |
|
|||
|
On 2010-02-08, Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
> On 2010-02-08, Keith Thompson <kst-u@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. > 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). > |
|
|||
|
On 2010-02-08, Keith Thompson <kst-u@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. -s -- Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated! |
|
|||
|
Andrew Poelstra <apoelstra@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 |
|
|||
|
On 2010-02-08, Ben Pfaff <blp@cs.stanford.edu> wrote:
> Andrew Poelstra <apoelstra@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. |
|
|||
|
On 2010-02-08, Kaz Kylheku <kkylheku@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. -s -- Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated! |
|
|||
|
Seebs <usenet-nospam@seebs.net> writes:
> On 2010-02-08, Keith Thompson <kst-u@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). -- Keith Thompson (The_Other_Keith) kst-u@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" |
|
|||
|
On 2010-02-08, Keith Thompson <kst-u@mib.org> wrote:
> Seebs <usenet-nospam@seebs.net> writes: >> On 2010-02-08, Keith Thompson <kst-u@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. -s -- Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated! |
|
|||
|
Keith Thompson <kst-u@mib.org> writes:
> Seebs <usenet-nospam@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. |
|
|||
|
Tor Rustad <bwzcab@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. |
|
|
![]() |
| Popular Tags in the Forum |
| braces, initializer, missing |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| missing braces around initializer | Boon | Newsgroup comp.lang.c | 5 | 05-13-2009 07:16 PM |
| Re: newbie: Missing values | Gerhard Hellriegel | Newsgroup comp.soft-sys.sas | 0 | 03-31-2008 08:55 AM |
| Re: proc format value assignment oddity - missing values | Sigurd Hermansen | Newsgroup comp.soft-sys.sas | 0 | 10-30-2005 10:38 PM |
| Re: Missing Values | Jim Groeneveld | Newsgroup comp.soft-sys.sas | 0 | 12-08-2004 07:45 AM |
| Re: Missing values---the simplest code | Jim Groeneveld | Newsgroup comp.soft-sys.sas | 0 | 12-03-2004 07:35 AM |