Please consider the following absurd but compiling code:
int main(int argc, char *argv[]) {
void *a, *b, *c, *d;
void *the_good_array[] = { a, b, c, d };
void *the_bad_array = { a, b, c, d };
return 0;
}
I accidentally produced something similar and, to my astonishment, it fully compiles.
- Why does it compile?
- What is
{ a, b, c, d }
supposed to mean as an initializer for a non array? Without the braces, I would understand it’s an accidental use of the,
operator resulting in the value of the last element (d
). But, braces? What are they supposed to mean here?
If possible, please refer to the C standard when answering.
Edit 1:
Compiles with both:
gcc -std=iso9899:1990 /tmp/bad_array.c # gcc (Debian 12.2.0-14)`
clang -std=iso9899:1990 /tmp/bad_array.c # Debian clang version 14.0.6
Edit 2:
Apparently
int i = { 0 };
is perfectly valid C.
I would like to know why but don’t have the standard to read it.
2
Answers
Having multiple intializer elements for single object is a constraint violation. N2176 (C17 standard draft) §6.7.9 Initialization:
In this case it’s depends on compiler what happens.
C compilers take backwards compatibility quite seriosly, and will accept a lot of code that would be considered invalid nowadays.
Braces are allowed allowed even around single expression:
With rules above,
initializer
can after a few steps be expanded to{ assignment-expression }
.Any initializer may have braces.
You can just omit them. From https://port70.net/~nsz/c/c11/n1570.html#6.7.9p11 :
Example:
The compiler informs you that:
Looks like the compiler chooses to ignore the "excess", taking only
a
.The short answer: the compiler was created by people in the way that compiles it. The GCC compiler writers chose to handle excess elements in scalar initializer in this particular way.
The language-lawyer answer: the code is invalid. It breaks the "shall" from the link above:
From https://port70.net/~nsz/c/c11/n1570.html#4p2 we know that:
The behavior is not defined, which means that anything can happen. Compiling is "anything".