编译器或定义行为的可能优化

时间:2013-04-09 23:56:23

标签: c++ c++11 undefined-behavior

如果有一个函数没有将任何引用或指针作为参数,它的返回类型是未使用的,并且它不会发出明显离开系统的调用(I / O调用,更改系统时间等),是否保证仅修改定义它的类(或根本不修改)?

我能想到的唯一例外情况如下:

void a(int b, int c){
    *((int*)b) = c; }

int main() {
    int d=1;
    a((int)(&d),d+1);
    return 0; }

是否保证定义?我知道int*int不必具有相同的大小,但是如果它们被定义为相同的大小,这是否必须起作用,或者它仍然是未定义的行为?

目标是查看某个功能是否可以合法优化(例如,如果您可以证明它没有副作用,则可以将其删除)。

2 个答案:

答案 0 :(得分:1)

标准保证reinterpret_cast用于从指针转换为合适的整数类型(大到足以容纳所有值)并返回到原始指针类型,保证产生相同的指针值。所以是的,这是有保证的:

int *p = new int(5);
intptr_t i = reinterpret_cast<intptr_t>(p);
// ...
int *q = reinterpret_cast<int*>(i);

assert(p == q);
*q = 10;
assert(*p == 5);

允许编译器删除没有副作用的代码,但是通过仅检查函数签名无法清楚地确定。对于内联函数,编译器可以看到代码,编译器有机会。对于在不同翻译单元中定义的函数,事情有点困难(如果函数足够小,则链接时优化仍然可行)。

请注意,这不仅限于通过value或const-reference获取参数的函数。如果编译器看到通过引用修改参数的函数,但它可以证明修改对象的值永远不会被再次读取,理论上它可以删除该调用。另一方面,除了简单的情况之外,我不打赌编译器会做任何事情。

答案 1 :(得分:0)

我会说这属于“定义明确的未定义行为”;它可能一直在工作(假设sizeof(int *)== sizeof(int)),但它在技术上是未定义的,并且很有可能某些编译器将来可能完全破坏它。另一个例子是使用union来重新解释一个浮点数为int的位。

另外,如果我没有指出LLVM的链接时间优化方向,那我就完全不对了。它旨在完成您在链接时所谈论的内容。它太棒了,在osx上“开箱即用”。他们还有一个非常简单的例子:http://llvm.org/docs/LinkTimeOptimization.html