提问人:user16217248 提问时间:10/17/2023 最后编辑:user16217248 更新时间:10/18/2023 访问量:99
条件运算符的未执行分支是否会导致编译时出现未定义的行为?
Can unexecuted branches of a conditional operator cause undefined behavior at compile-time?
问:
据我所知,如果至少条件和执行的分支是编译时常量,则可以在编译时计算三元运算符。但是,如果其中一个未执行的参数会调用未定义的行为,该怎么办?在运行时,未执行的分支不会导致未定义的行为,因为在这种情况下,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 值不会编译,因为编译器将尝试评估哪些行为是未定义的行为,无论是在编译时还是在运行时。如果我更改为其他一些无效构造,例如 *(int *)0
,则行为不会改变。1/0
1/0
我的问题是,在编译时上下文中,未定义/无效/非编译时构造(不包括语法错误)可能出现在三元运算符的未执行分支中的这种行为不会引起问题,这是特定于 GCC 还是可移植的?
根据文档,GCC有:__builtin_constant_p()
static const int table[] = { __builtin_constant_p (EXPRESSION) ? (EXPRESSION) : -1, /* … */ };
即使 EXPRESSION 不是常量表达式,这也是一个可接受的初始值设定项,...
这个示例用法表明 GCC 明确允许我提出的要求,但标准 C 是否允许?__builtin_constant_p()
永远不会执行的代码可以调用未定义的行为吗?是一个不同的问题,因为问题中列出的代码位于函数的语句中。我的问题特别关于编译时值,例如全局/静态变量的初始值设定项等。if
main()
答:
该行为完全由 C 标准定义,无论编译器何时选择计算表达式。
不计算条件运算符的未选择操作数 (C 2018 6.5.15 4)。C 标准指定程序的行为是不计算操作数,无论条件表达式是在编译时还是在运行时实际计算,都是如此。
除以零等运算只有在计算时才具有未定义的行为。
对于一般操作,6.5 5 表示“如果在表达式计算期间发生异常情况(即,如果结果未在数学上定义或不在其类型的可表示值范围内),则该行为是未定义的。因此,这些行为只能在“表达式评估期间”出现。除以零有点不同,因为 6.5.5 5 表示除以零具有未定义的行为,与 6.5 5 分开。但是,这是在语义子句中,它告诉我们计算表达式的行为是什么。
下一个:对类型进行编译时操作
评论
constexpr
,它在这里可能很有用。sizeof(char) == 1 ? 1 : 1/0;
;
sizeof
==
? :
.
1
0