这些属性允许编译器知道在不知道它是如何实现的情况下忽略对函数的调用是安全的。
纯属性基本上说功能结果只取决于函数参数和全局状态;另外,函数本身不会改变全局状态。
如果你调用一个纯函数两次,它保证返回相同的结果;但是,如果您在调用之间改变全局可见状态,则担保不再成立。
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()。