来自GCC文档:
许多函数不检查除参数之外的任何值,并且 除了返回值之外没有任何影响。基本上这只是 比上面的纯属性稍微严格一些,因为 函数不允许读取全局内存。
我的问题是全局
const
值是否算作全局内存。我认为确实如此,但奇怪的是,我明确标记为不变的值可能会否定此处可能的优化。
例如:
int const ConstantModulusValue = 3;
int foo(int value) {
return foo % ConstantModulusValue;
}
根据我的理解,使用
ConstantModulusValue
意味着这个函数不应该被标记为 const
,这对我来说又显得很奇怪。标记这个我看不到的const
有危险吗?
这些属性允许编译器知道在不知道函数是如何实现的情况下省略对函数的调用是否安全。
pure属性基本上表示函数结果仅取决于函数参数和全局状态;此外,函数本身不会改变全局状态。
如果你调用一个纯函数两次,它保证返回相同的结果;但是,如果您在调用之间改变全局可见状态,则保证不再成立。
const属性更强,即使全局状态发生变化,函数仍然应该返回相同的结果;因此在更多情况下优化对 const 函数的冗余调用是安全的。
如果可以保证状态不会改变,那么读取全局状态应该不是问题(请注意,将全局标记为 const 并不总是能保证这一点)。
举个例子,考虑这个程序:
int foo(int) __attribute__((pure));
int bar(int) __attribute__((const));
void unknown();
int test1(int a)
{
int x = foo(a);
int y = foo(a);
return x + y;
}
int test2(int a)
{
int x = bar(a);
int y = bar(a);
return x + y;
}
int test3(int a)
{
int x = foo(a);
unknown();
int y = foo(a);
return x + y;
}
int test4(int a)
{
int x = bar(a);
unknown();
int y = bar(a);
return x + y;
}
用 gcc 4.8.1 编译它并分析程序集,发现
test1()
和 test2()
都只调用各自的函数一次,然后将结果乘以 2; test3()
执行 3 次调用 - 2 次调用 foo 和 1 次调用未知; test4()
调用 bar(),然后调用unknown(),并返回 bar() 的结果乘以 2。
此行为与上面的解释相符 -unknown() 可以改变全局状态,因此编译器无法消除对 foo() 的额外调用,但可以消除对 bar() 的额外调用。