?:
运算符。但是,如果“未执行”参数之一会调用未定义的行为怎么办?在运行时,未执行的分支不会导致未定义的行为,因为在这种情况下,C 将彻底崩溃。 但这适用于编译时间吗?
static const int GLOBAL_VARIABLE = sizeof(char) == 1 ? 1 : 1/0;
// sizeof(char) is guaranteed to be 1 so the 1/0 is never evaluated
这一定会导致定义的行为吗?这似乎适用于
GCC。正如预期的那样,将表达式更改为编译时 false 值不会编译,因为编译器将尝试评估
1/0
,无论是在编译还是运行时,这都是未定义的行为。如果我将 1/0
更改为其他一些无效构造,例如
*(int *)0
,则行为不会改变。我的问题是,未定义/无效/非编译时构造(不包括语法错误)可能出现在编译时上下文中三元运算符的未执行分支中的行为将不会导致问题,这是 GCC 特有的还是便携式的? 根据 docs
GCC 有__builtin_constant_p()
:
static const int table[] = {
__builtin_constant_p (EXPRESSION) ? (EXPRESSION) : -1,
/* … */
};
即使的示例用法表明 GCC 明确允许我要求的内容,但是标准 C 允许吗?EXPRESSION不是常量表达式,这也是可接受的初始值设定项,...这个
__builtin_constant_p()
条件运算符的未选择操作数不会被求值 (C 2018 6.5.15 4)。 C 标准指定程序的行为是不计算操作数,无论条件表达式是在编译时还是运行时实际计算,都是如此。
对于一般操作,6.5 5 说“如果在表达式求值期间发生
异常条件
(即,如果结果未在数学上定义或不在其类型的可表示值范围内),则行为未定义”。因此,此类行为只能在“表达式求值期间”出现。除以零有点不同,因为 6.5.5 5 说除以零有未定义的行为,与 6.5 5 不同。然而,这是在一个语义子句中,它告诉我们评估表达式的行为是什么。