考虑这个程序:
#include <stdio.h>
int main(void)
{
int x;
while ( 1 == scanf("%d", &x) )
printf("%c\n", "hello"[x]);
}
编译器必须成功编译,因为只要用户没有输入0
- 4
范围之外的任何数字,程序就没有UB。
然而,根据this thread,UB可以及时返回。现在考虑这个程序:
int main(void)
{
printf("hello\n");
"hello"[6];
}
对此程序的任何调用都会导致未定义的行为,并且因为这可能是时间旅行,所以此程序在任何调用中的整个行为都是未定义的。因此,编译器可以拒绝该程序而不生成可执行文件吗? (我们可能会说UB会及时回到编译阶段!)
答案 0 :(得分:14)
编译器是否可以拒绝该程序而不生成可执行文件?
是。未定义行为的定义是:
本国际标准没有要求的行为 [注意:当本国际标准忽略任何明确的行为定义或程序使用错误的构造或错误数据时,可能会出现未定义的行为。允许的未定义行为 范围从完全忽略不完全结果的情况,到翻译或程序执行期间的行为,以文件的方式表征环境(有或没有发出诊断信息),终止翻译或执行(发布一个诊断消息)。许多错误的程序结构不会产生未定义的行为;他们需要被诊断出来。 - 结束说明]
答案 1 :(得分:4)
添加到Jonathan的回答中。
第二个程序调用未定义的行为,编译器有权停止转换,因为未定义的行为不受限制(c11,3.4.3p1)。
第一个程序可能会调用未定义的行为,但编译器无法停止转换,因为并非所有执行路径都会产生未定义的行为。
在Defect Report #109中,C委员会说:
此外,如果给定程序的每个可能执行都会导致未定义的行为,则给定的程序不严格符合。 一致的实现必须简单地转换严格符合的程序,因为该程序的某些可能的执行会导致不确定的行为。