0

来自GCC 文档

许多函数除了参数之外不检查任何值,并且除了返回值之外没有任何效果。基本上,这只是比上面的纯属性稍微严格的类,因为不允许函数读取全局内存。

我的问题是全局const值是否算作全局内存。我认为确实如此,但是我明确标记为不变的值可能会否定此处可能的优化,这似乎很奇怪。

例如:

int const ConstantModulusValue = 3;

int foo(int value) {
    return foo % ConstantModulusValue;
}

根据ConstantModulusValue我的理解,使用 意味着不应标记此功能,这const对我来说再次显得很奇怪。const标记这个我看不到的东西有什么危险吗?

4

1 回答 1

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() 的额外调用。

于 2014-02-10T02:51:10.553 回答