我正在使用Intel C++编译器12.0,并正在编写类似于以下的程序,非常简单明了。 while 循环应该在第一次运行时停止。但是,当我使用 Intel 编译器使用 /O2 标志构建代码时,while 循环永远不会停止。如果我禁用优化,或使用 Visual C++,循环将正常退出。如果我将 pt->flag 更改为 p.flag(我认为这是同一件事),循环也会正常退出。我想这和Intel的优化有关系。这是英特尔编译器中的错误吗?或者我在这里错过了什么?
#include <iostream>
using namespace std;
struct para {
int i;
int flag;
};
int main(int argc, char **argv)
{
para p;
p.i = 0;
p.flag = 1;
para * pt = &p;
cout << "loop started" << endl;
int i;
while (p.flag) {
if (p.i == 0) {
for (i=0; i<1; i++) {
if (p.flag != 1)
break;
}
if (i==1) {
pt->flag = 0;
}
}
}
cout << "loop stopped" << endl;
return 1;
}
更新: 谢谢大家的回答。我对“指针别名”的解释感到困惑。如果 p 在寄存器中并且 pt 无法访问它,为什么下面的代码会破坏 intel 编译器的 while 循环?首先“pt->flag = 0;”永远不会生效,因为 i=0。其次,即使它有效,“指针别名”不应该阻止 p 被修改吗?
顺便说一句:有人可以告诉我如何使用英特尔编译器在 Visual Studio 中打开/关闭指针别名吗?谢谢!
#include <iostream>
using namespace std;
struct para {
int i;
int flag;
};
int main(int argc, char **argv)
{
para p;
p.i = 0;
p.flag = 1;
para * pt = &p;
cout << "loop started" << endl;
int i=0;
while (p.flag) {
if (p.i == 0) {
//for (i=0; i<1; i++) {
// if (p.flag != 1)
// break;
//}
if (i==1) {
pt->flag = 0;
}
}
}
cout << "loop stopped" << endl;
return 1;
}
这种情况称为“指针别名”。你有一个变量 p
和一个指针
pt
,它指向与 p
相同的东西。如果编译器可以假设给定变量只有一个“名称”,则可以使用许多优化,并且您的编译器的 /O2
可能会启用此假设。例如,编译器可以在循环期间将p
的所有成员变量保留在寄存器中,这显然无法通过内存指针访问。检查编译器文档,了解如何告诉它不要假设没有指针别名。这可能是编译器开关或
#pragma
。