数组初始化中的三元运算符

Ternary operator in array initalization

在数组初始化中使用三元运算符是否使用有效的 C99 常量?

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

没有。来自 clang:

example.c:4:15: warning: initializer for aggregate is not a compile-time
      constant [-Wc99-extensions]
        int foo[] = {bar? 9U:20U};
                     ^~~~~~~~~~~

是的,你可以。从初始化器的语法生成开始:

6.7.8 初始化

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

该部分中对初始化程序的唯一相关(在我看来)约束是它必须是具有静态存储持续时间的对象的常量表达式:

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

接着 assignment-expression 的制作,我们看到

6.5.16 赋值运算符

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

条件表达式也是有效的赋值表达式。所以它可能在初始化器列表中显示为初始化器。唯一需要检查的是它可以是具有静态存储持续时间的对象的有效常量表达式。

6.6 常量表达式

constant-expression:
         conditional-expression

具有以下约束和语义的段落:

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.

所以以上所有内容构成了以下有效程序:

#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};
}

此外,对于具有自动存储期限的对象,您不限于常量表达式作为条件表达式的两个子表达式。它们也可以引用范围内的任何对象。