来自GCC docs:
除了参数之外,许多函数都不会检查任何值 除了返回值之外没有任何效果。基本上这只是 比上面的纯属性略强一些,因为 函数不允许读取全局内存。
我的问题是全局const
值是否算作全局内存。我认为它确实如此,但我明确标记为不变的值似乎很奇怪,这可能会否定可能的优化。
例如:
int const ConstantModulusValue = 3;
int foo(int value) {
return foo % ConstantModulusValue;
}
根据我的理解,使用ConstantModulusValue
意味着不应将此功能标记为const
,这对我来说似乎很奇怪。标记这个const
是否有一些危险我不明白。
答案 0 :(得分:1)
这些属性允许编译器知道在不知道它是如何实现的情况下省略对函数的调用是否安全。
纯属性基本上说函数结果只取决于函数参数和全局状态;另外,函数本身不会改变全局状态。
如果你两次调用纯函数,它会保证返回相同的结果;但是,如果您在调用之间改变全局可见状态,则保证不再成立。
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()的额外调用。