C ";“可观察到的行为”;在UB的上下文中;“未定义的行为”;
(这个问题最初是由本答案下的注释提出的,但这里严格从C语言的角度提出,不涉及任何并发或多线程。) 考虑以下代码:C ";“可观察到的行为”;在UB的上下文中;“未定义的行为”;,c,language-lawyer,C,Language Lawyer,(这个问题最初是由本答案下的注释提出的,但这里严格从C语言的角度提出,不涉及任何并发或多线程。) 考虑以下代码: #define BUFSIZ 10 char buf[BUFSIZ]; void f(int *pn) { buf[*pn]++; *pn = (*pn + 1) % BUFSIZ; } int main() { int n = 0; f(&n); return n; } 问题:C“as-if”规则是否允许编译器按如下方式重写代
#define BUFSIZ 10
char buf[BUFSIZ];
void f(int *pn)
{
buf[*pn]++;
*pn = (*pn + 1) % BUFSIZ;
}
int main()
{
int n = 0;
f(&n);
return n;
}
问题:C“as-if”规则是否允许编译器按如下方式重写代码
void f(int *pn)
{
int n = *pn;
*pn = (*pn + 1) % BUFSIZ;
buf[n]++;
}
一方面,上述内容不会改变所编写程序的可观察行为
另一方面,f
可能会被无效索引调用,可能来自另一个翻译单元:
int g()
{
int n = -1001;
f(&n);
}
在后一种情况下,代码的两个变体在访问越界数组元素时都会调用UB。然而,原始代码将在传递到f
(=-1001)的值处离开*pn
,而重写的代码只有在修改*pn
(到0
)后才会进入UB land
这种差异会被认为是“可观察的”吗?或者,回到实际问题,C标准中是否有任何东西特别允许或排除这种类型的代码重写/优化
- 对易失性对象的访问严格按照抽象机器的规则进行评估
- 在程序终止时,写入文件的所有数据应与根据抽象语义执行程序所产生的结果相同
- 交互设备的输入和输出动态应按照7.21.3的规定进行。这些要求的目的是尽可能快地显示无缓冲或行缓冲输出,以确保提示消息实际出现在 等待输入的程序
这根本不是事实。输入可能导致未定义的行为。我可以从一个程序中获得部分输出,然后将该输出传递到宇宙中一个因因果关系而断开的部分。之后,我可以给程序一个导致UB的输入。已经获得的有效输出不能被撤销(这在物理上是不可能的;我们已经将其传达给了一个因果分离的时空区域)。也就是说,即使UB导致了一些灾难性事件,比如超新星爆炸,前面的结果是不会被破坏的。@kaz:我认为时间旅行是不可能的,不管C标准是否允许。尽管如此,该标准免除了执行行为未定义程序的所有责任。当然,这种自由延伸到遵守宇宙的物理定律,我认为输入导致的UB很可能不会追溯到程序执行,但这不是标准所要求的,即使是常识所要求的……无论如何