这是一个例子来说明我的问题,其中涉及一些我不能在这里发布的更复杂的代码.
#include <stdio.h>
int main()
{
int a = 0;
for (int i = 0; i < 3; i++)
{
printf("Hello\n");
a = a + 1000000000;
}
}
Run Code Online (Sandbox Code Playgroud)
这个程序在我的平台上包含未定义的行为,因为它a会在第3个循环中溢出.
这是否会使整个程序具有未定义的行为,或者仅在溢出实际发生之后?编译器是否可能a 会解决溢出问题,因此它可以声明整个循环未定义,并且不会打扰运行printfs,即使它们都在溢出之前发生?
(标记为C和C++,即使它们不同,因为如果它们不同,我会对这两种语言的答案感兴趣.)
我不确定我是否完全理解未定义行为可能危及程序的程度.
假设我有这段代码:
#include <stdio.h>
int main()
{
int v = 0;
scanf("%d", &v);
if (v != 0)
{
int *p;
*p = v; // Oops
}
return v;
}
Run Code Online (Sandbox Code Playgroud)
这个程序的行为是否仅针对v非零的情况而定义,或者即使v为零也未定义?
考虑
void swap(int* a, int* b)
{
if (a != b){
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
}
int main()
{
int a = 0;
int b = 1;
swap(&a, &b); // after this b is 0 and a is 1
return a > b ? 0 : a / b;
}
Run Code Online (Sandbox Code Playgroud)
swap 试图欺骗编译器不优化程序.
是否定义了此程序的行为?a / b是永远无法达到的,但如果是,那么你会得到除零.
例如,如果我们有一个std::array并且我们使用constexpr编译器实例化一个超出绑定的元素将不会报告错误:
constexpr int EvaluateSpecialArrayIndex(int a)
{ return a * sizeof(int); }
array<int, 5> arr;
cout << arr[98] << endl; //compiles fine
cout << arr[EvaluateSpecialArrayIndex(4)] << endl; //the same as above
Run Code Online (Sandbox Code Playgroud)
我们不能以某种方式限制这个吗?
考虑这个程序:
#include <stdio.h>
int main(void)
{
int x;
while ( 1 == scanf("%d", &x) )
printf("%c\n", "hello"[x]);
}
Run Code Online (Sandbox Code Playgroud)
编译器必须成功编译,因为程序没有UB,只要用户不输入范围之外的任何数字0- 4.
但是,根据这个线程, UB可以及时返回.现在考虑这个程序:
int main(void)
{
printf("hello\n");
"hello"[6];
}
Run Code Online (Sandbox Code Playgroud)
对此程序的任何调用都会导致未定义的行为,并且因为这可能是时间旅行,所以此程序在任何调用中的整个行为都是未定义的.因此,编译器可以拒绝该程序而不生成可执行文件吗?(我们可能会说UB回到编译阶段!)
我有一个代码片段从这里:
volatile int volatileInt;
int usualInt;
void function (unsigned x, unsigned y, unsigned z)
{
volatileInt = 0;
usualInt = (x % y) / z;
}
int main()
{
function(rand(), rand(), rand());
}
Run Code Online (Sandbox Code Playgroud)
我使用Visual C++ 10编译/O2并获得此反汇编:
00403940 push ebx
00403941 push esi
276: function(rand(), rand(), rand());
00403942 mov esi,dword ptr [__imp__rand (4050C0h)]
00403948 push edi
00403949 call esi
0040394B mov edi,eax
0040394D call esi
0040394F mov ebx,eax
00403951 call esi
00403953 xor edx,edx
00403955 div eax,ebx …Run Code Online (Sandbox Code Playgroud)