如果有一个函数没有将任何引用或指针作为参数,它的返回类型是未使用的,并且它不会发出明显离开系统的调用(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
不必具有相同的大小,但是如果它们被定义为相同的大小,这是否必须起作用,或者它仍然是未定义的行为?
目标是查看某个功能是否可以合法优化(例如,如果您可以证明它没有副作用,则可以将其删除)。
答案 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