以下代码进入GCC的无限循环:
#include <iostream>
using namespace std;
int main(){
int i = 0x10000000;
int c = 0;
do{
c++;
i += i;
cout << i << endl;
}while (i > 0);
cout << c << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
所以这是交易:有符号整数溢出在技术上是未定义的行为.但是x86上的GCC使用x86整数指令实现整数运算 - 它包含溢出.
因此,我本来期望它包装溢出 - 尽管事实上它是未定义的行为.但事实显然并非如此.那么我错过了什么?
我使用以下方法编译:
~/Desktop$ g++ main.cpp -O2
Run Code Online (Sandbox Code Playgroud)
GCC输出:
~/Desktop$ ./a.out
536870912
1073741824
-2147483648
0
0
0
... (infinite loop)
Run Code Online (Sandbox Code Playgroud)
禁用优化后,没有无限循环且输出正确.Visual Studio也正确编译它并给出以下结果:
正确的输出:
~/Desktop$ g++ main.cpp
~/Desktop$ ./a.out
536870912
1073741824
-2147483648
3
Run Code Online (Sandbox Code Playgroud)
以下是一些其他变体:
i *= 2; // Also …Run Code Online (Sandbox Code Playgroud) 从下面的代码sizeof(Base) == 24和sizeof(Derived) == 24.
为什么他们的尺寸相同?
在Base课堂上我们有3名成员,在Derived课堂上我们有另一名成员.
class Base
{
private:
double d;
protected:
long l;
public:
int i;
};
class Derived : public Base
{
private:
float f;
};
Run Code Online (Sandbox Code Playgroud) 在一般情况下,从(动态)下降Base到其中一个派生类是(非常应得的)未定义行为Derived
class Base
{
public:
virtual void foo()
{ /* does something */ }
int a;
}
class Derived : public Base
{
public:
virtual void foo()
{ /* does something different */ }
double b;
}
Base obj;
Derived derObj = *static_cast<Derived *>(&obj); // <- here come the demons
Run Code Online (Sandbox Code Playgroud)
在目前的编译器实现方法中,这里显然至少存在Vtable和b中包含垃圾值的值不一致的问题.因此,在这些条件下,标准没有定义向下转换的行为是有道理的.
然而,我很想知道在特定情况下这条规则是否有一些让步? 举个例子:
class Base
{
public:
void foo()
{ /* does something */ }
int a = 1;
double b = 2.;
} …Run Code Online (Sandbox Code Playgroud)