29

I came across the below initialization , it is seen that VS2012 shows an error complaining about too many initializers. in GCC it seems to return the first element as the value.

why is this peculiar initialization supported in GCC?

#include <stdio.h>

int main()
{
    int q = {1,2};
    char c = {'s','t','\0'};  /* c is 's' */
    printf("%d\n",q); /* prints 1*/
}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
bare_metal
  • 1,134
  • 9
  • 20
  • 7
    I wonder what it's doing with the remaining initializers:( – Martin James Feb 09 '15 at 14:58
  • @Martin please see this http://stackoverflow.com/questions/28394871/const-char-a-string1-string2-and-pointer-arithametic . I got really bashed for this question, but it gets interesting when strings are involved :) – bare_metal Feb 09 '15 at 15:00
  • Have you seen this in code? It seems like a bad idea, even if the compiler allows it. – Degustaf Feb 09 '15 at 15:00
  • 14
    If you enable warnings `gcc` will be really pissed off with this. – Iharob Al Asimi Feb 09 '15 at 15:01
  • 1
    GCC 4.8.3 here outputs a warning *by default* (that is, without `-Wall` or anything). – Tim Čas Feb 09 '15 at 15:02
  • 2
    Lots of warnings... http://coliru.stacked-crooked.com/a/6691f8768208b710 – Deduplicator Feb 09 '15 at 15:03
  • @Deduplicator that's what I mean, why would this be useful anyway? – Iharob Al Asimi Feb 09 '15 at 15:04
  • [A quick primer on initialization in C.](http://publications.gbdirect.co.uk/c_book/chapter6/initialization.html) This, combined with @haccks answer, should illuminate why it's only a warning. – bishop Feb 09 '15 at 15:15
  • 1
    My first thought was that it's a comma operator, discarding the `1` and yielding `2`. `1,2` is a valid expression. But the grammar requires an *assignment-expression* in that context, so a top-level comma operator is not permitted. – Keith Thompson Feb 09 '15 at 17:15
  • @KeithThompson allowing comma operator in this content would be horrible! – M.M Feb 09 '15 at 19:43
  • @MattMcNabb: Agreed, it would create ambiguities. (Though of course comma operators are allowed as long as they're not at the top level.) – Keith Thompson Feb 09 '15 at 19:48

1 Answers1

37

C11: 6.7.9 Initialization (p11):

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

Therefore, this is allowed

int q = {1};   

You can enclose the initializer for scalar objects in braces ({}). Note the verb shall is used here. The standard says:

5.1.1.3 Diagnostics (P1):

A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined

So, it is up to the compiler how it handles

int q = {1,2}; 

Compiled on GCC 4.8.1 with flags -pedantic -Wall -Wextra and it raised a warning

[Warning] excess elements in scalar initializer [enabled by default]   

Now the question is: What happend with the remaining initializers? It's a bug.


Note: C11: 6.5.17 (p3) says that the comma operator cannot appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists of initializers).

Do not confused the , in {1,2} with comma operator. As Keith Thompson pointed out that, the expression in initializer to be an assignment-expression and it must not contain comma operator at top-level. That means it can be used within a parenthesized expression or within the second expression of a conditional operator in such contexts. In the function call

f(a, (t=3, t+2), c)

the function has three arguments, the second of which has the value 5.

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
  • 1
    so the remaining initializers are ignored? – bare_metal Feb 09 '15 at 15:06
  • 1
    do you remember the following question , http://stackoverflow.com/questions/28394871/const-char-a-string1-string2-and-pointer-arithametic , The result is basically due to this? – bare_metal Feb 09 '15 at 15:09
  • 1
    "*Shall*" being the operative verb in the spec. For a long while, [GCC has been avant garde in its initialization support.](https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html) – bishop Feb 09 '15 at 15:12
  • @bare_metal; See the updated answer. And please do not mix two entirely different data types for any behavior. – haccks Feb 09 '15 at 15:48
  • It's worth mentioning that the grammar requires the expression to be an *assignment-expression*, which means that the top-level operator may not be a comma operator. (This is necessary to avoid ambiguity.) – Keith Thompson Feb 09 '15 at 18:22
  • @KeithThompson; Are you sure that expression is to be *assignment-expression*? – haccks Feb 09 '15 at 18:37
  • 1
    @haccks: Yes. [N1570](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) 6.7.9p1: the syntax of an *initializer* is one of *assignment-expression*, `{` *initializer-list* `}`, or `{` *initializer-list* `,` `}`. (Note that an *assignment-expression* needn't have an assignment operator; any expression whose top-level operator is not a comma operator is an *assignment-expression*.) – Keith Thompson Feb 09 '15 at 18:41
  • @KeithThompson; Thanks for the valuable comment. Added that to the answer. – haccks Feb 09 '15 at 19:20
  • 1
    An *assignment-expression* may contain a comma operator, just not at the top level. `int q = { (1, 2) };` would be legal (but silly). – Keith Thompson Feb 09 '15 at 19:22
  • @KeithThompson; Example were given in the standard but I skipped that. – haccks Feb 09 '15 at 19:29
  • The linked bug report is about `gcc` segfaulting (the compiler, not the user executable) when faced with some ill-formed code, I don't think that bug is directly relevant to this question. Instead, gcc allows excess initializers on purpose (and ignores them) when in GNU mode. – M.M Feb 09 '15 at 19:47
  • @MattMcNabb; Not directly but it is related to this question. – haccks Feb 09 '15 at 20:28
  • @haccks I mean, the answer to "where did the excess initializers go?" isn't "a bug"; instead they are being ignored on purpose. – M.M Feb 09 '15 at 20:30
  • @MattMcNabb; For what purpose? – haccks Feb 09 '15 at 20:30
  • @haccks you'd have to ask the gcc developers that . Probably for backwards compatibility at this stage. – M.M Feb 09 '15 at 20:42
  • 6.7.9p11 is neither a syntax rule nor a constraint. Rather, 4p2 ("If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined.") applies. This arguably also violates 6.7.9p2 ("No initializer shall attempt to provide a value for an object not contained within the entity being initialized.") though, which is a constraint. – T.C. Feb 10 '15 at 09:08