11

I don't have access to the C11 specification, therefore I can't investigate this bug.

The following declaration rises an error during compilation:

int why[2] =  1 == 1 ? {1,2} : {3,4}; 

The error is: expected expression before { and: expected expression before :

Rudi Rüssel
  • 439
  • 4
  • 13

3 Answers3

12

This is not valid C11.

You can only initialize an array with an initializer-list not with an expression.

int why[2] = { ... };  // initializer-list {}

Moreover, 1 == 1 ? {1,2} : {3,4} is not a valid C expression because {1, 2} is not a C expression.

Just for information using compound literals you can have something close to what you want using a pointer object:

int *why = (1 == 1) ? (int[2]) {1,2} : (int[2]) {3,4};
ouah
  • 142,963
  • 15
  • 272
  • 331
  • 1
    @RudiRüssel yes, that one is valid but there is no `{1, 2}` expression here and `works` is not an array. – ouah Apr 08 '13 at 11:22
  • 1
    @RudiRüssel: Expressions are things with values. `6 * 7` has a value. Initializer lists are not expressions; they are just a syntax for describing multiple values to be put into at object when it is initialized. The source code `{1, 2}` is not a value or an object or anything you can manipulate. It is just a description of what to put into an array. Because it is not an expression, you cannot operate on it; you cannot use it as an operand in for `? :` or for other operators. – Eric Postpischil Apr 08 '13 at 11:33
  • 1
    +love your solution very nice I means `int *why = (1 == 1) ? (int[2]) {1,2} : (int[2]) {3,4};` – Grijesh Chauhan Apr 08 '13 at 11:43
  • @Eric Thank you! In the C EBNF a **block** is a __statement__ but not an __[conditional-]expression__ – Rudi Rüssel Apr 08 '13 at 11:51
  • @CustomCalc Incorrect comment coming from an incorrect assumption. In a function a compound literal has automatic storage duration and its lifetime ends on exit from the block where it appears. Outside the body of a function it has static storage duration and its lifetime is the entire execution of the program. – ouah Jan 18 '15 at 14:09
  • @ouah, wow mind blown. So if I take this into C++ I get a dangerous address to a temporary, but in C99 and up it's basically an unnamed object in the current scope. Thank you. – CustomCalc Jan 18 '15 at 19:23
  • @ouah, what is the existing duration of (int[2]) {1,2} may I ask? will it be reclaimed outside the scope? – – kjhhgt76 Jul 15 '22 at 02:24
2

from Charles Bailey's answer here: Gramma from conditional-expression

   conditional-expression:
        logical-OR-expression
        logical-OR-expression ? expression : conditional-expression

And

  1 == 1 ? {1,2} : {3,4}; 
           ^        ^       are not expressions  

that is the reason compiler gives error like:

error: expected expression before ‘{’ token    // means after ?
error: expected expression before ‘:’ token    // before :

Edit as @Rudi Rüssel commented:

following is a valid code in c:

int main(){
    {}
    ;
    {1,2;}
}

we use {} to combine statements ; in C.

note: if I write {1,2} then its error (*expected ‘;’ before ‘}’ token*), because 1,2 is an expression but not a statement.

For OP: what is The Expression Statement in C and what is Block Statement and Expression Statements

edit2:
Note: How @ouah uses typecase to convert it into expression, yes:

To understand run this code:

int main(){
 printf("\n Frist = %d, Second =  %d\n",((int[2]){1,2})[0],((int[2]) {1,2})[1]);
}

It works like:

~$ ./a.out 

 Frist = 1, Second =  2
Community
  • 1
  • 1
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
0

Initializer lists are not expressions, so they cannot be used in expressions.

I suggest you leave the array uninitialized and use memcpy.

int why[2];
memcpy( why, 1 == 1 ? (int[2]){1,2} : (int[2]){3,4}, sizeof why );
CustomCalc
  • 2,182
  • 3
  • 12
  • 9