Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ternary operator in array initalization

Tags:

c

c99

Is using the tenary operator within array initalization with constants valid C99?

uint8_t foo[] = {bar? 9U:20U};
like image 817
user259819 Avatar asked Feb 07 '18 06:02

user259819


2 Answers

Yes, you may. Starting from the grammar production for an initalizer:

6.7.8 Initialization

initializer:
       assignment-expression
       { initializer-list }
       { initializer-list , }
initializer-list:
       designation(optional) initializer
       initializer-list , designation(optional) initializer

The only relevant (in my opinion) constraint on the initializer in that section is that it must be a constant expression for objects with static storage duration:

All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.

Following it onward to the production of assignment-expression, we see that

6.5.16 Assignment operators

assignment-expression:
        conditional-expression
        unary-expression assignment-operator assignment-expression

A conditional expression is a valid assignment expression as well. So it may appear as an initializer in an initializer list. The only thing left to check is that it can be a valid constant expression for objects with static storage duration.

6.6 Constant expressions

constant-expression:
         conditional-expression

With the following constraint and semantic paragraphs:

Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.

More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following:

  • an arithmetic constant expression,
  • a null pointer constant,
  • an address constant, or
  • an address constant for an object type plus or minus an integer constant expression.

So all of the above makes for the following valid program:

#include <stdint.h>
#include <stdlib.h>

#define BAR 1

uint8_t foo[] = {BAR ? 9U:20U};

int main(void) {
   int bar = rand();
   uint8_t foo[] = {bar ? 9U:20U};
}

Furthermore, for objects with automatic storage duration, you aren't limited to constant expressions as the two sub-expressions of the conditional expression. They can refer to any object in scope as well.

like image 133
StoryTeller - Unslander Monica Avatar answered Sep 28 '22 06:09

StoryTeller - Unslander Monica


No. From clang:

example.c:4:15: warning: initializer for aggregate is not a compile-time
      constant [-Wc99-extensions]
        int foo[] = {bar? 9U:20U};
                     ^~~~~~~~~~~
like image 38
Carl Norum Avatar answered Sep 28 '22 08:09

Carl Norum