C语言 条件运算符的未执行分支会导致编译时的未定义行为吗?

xoshrz7s  于 2023-11-17  发布在  其他
关注(0)|答案(1)|浏览(79)

据我所知,如果至少条件和执行的分支是编译时常量,则可以在编译时计算三元?:运算符。但是,如果其中一个 unexecuted 参数会调用未定义的行为呢?在运行时,未执行的分支不会导致未定义的行为,因为在这种情况下,C将break thoroughly
但是,这适用于编译时吗?

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,
  /* … */
};


这是一个可接受的初始化器,即使 EXPRESSION 不是常量表达式,...
这个__builtin_constant_p()的例子表明GCC明确地允许我所要求的,但是标准C允许吗?
Can code that will never be executed invoke undefined behavior?是一个不同的问题,因为问题中列出的代码在main()函数的if语句中。我的问题是特别关于编译时值,例如全局/静态变量的初始化器等。

l7mqbcuq

l7mqbcuq1#

行为完全由C标准定义,无论编译器选择何时计算表达式。
条件运算符的操作数不求值(C 2018 6.5.15 4)C标准规定程序的行为是操作数不求值,无论条件表达式实际上是在编译时还是运行时求值,都是如此。
诸如被零除之类的运算只有在计算时才具有未定义的行为。
对于一般的操作,6.5.5表示“如果在表达式求值期间出现 * 异常条件 *,(即,如果结果没有数学定义或不在其类型的可表示值范围内),行为是未定义的。”所以这类行为只能在“表达式求值期间”出现。除以零有点不同,因为6.5.5 5说除以零有未定义的行为,与6.5 5不同。然而,这是在一个语义子句中,告诉我们计算表达式的行为是什么。

相关问题