【问题标题】:const gcc function attribute and a global const variablesconst gcc 函数属性和全局 const 变量
【发布时间】:2014-02-10 02:20:51
【问题描述】:
来自GCC docs:
许多函数不检查除参数之外的任何值,并且
除了返回值之外没有任何影响。基本上这只是
比上面的纯属性稍微严格的类,因为
函数不允许读取全局内存。
我的问题是全局 const 值是否算作全局内存。我认为确实如此,但我明确标记为不变的值可能会否定此处可能的优化,这似乎很奇怪。
例如:
int const ConstantModulusValue = 3;
int foo(int value) {
return foo % ConstantModulusValue;
}
在我的理解中,ConstantModulusValue 的使用意味着这个函数不应该被标记为const,这对我来说再次显得很奇怪。标记这个我看不到的const 有什么危险吗?
【问题讨论】:
标签:
gcc
clang
function-attributes
【解决方案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() 的额外调用。