为什么没有对GCC中错误使用_属性_((pure))给出警告?

为什么没有对GCC中错误使用_属性_((pure))给出警告?,c,gcc,function-attributes,C,Gcc,Function Attributes,我试图理解纯函数,并且一直在阅读有关该主题的文章。我编写的最小示例程序如下所示: #include <stdio.h> static int a = 1; static __attribute__((pure)) int pure_function(int x, int y) { return x + y; } static __attribute__((pure)) int impure_function(int x, int y) { a++

我试图理解纯函数,并且一直在阅读有关该主题的文章。我编写的最小示例程序如下所示:

#include <stdio.h>

static int a = 1;

static __attribute__((pure)) int pure_function(int x, int y)
{
        return x + y;
}

static __attribute__((pure)) int impure_function(int x, int y)
{
        a++;
        return x + y;
}

int main(void)
{
        printf("pure_function(0, 0) = %d\n", pure_function(0, 0));
        printf("impure_function(0, 0) = %d\n", impure_function(0, 0));

        return 0;
}
#包括
静态int a=1;
静态函数(intx,inty)
{
返回x+y;
}
静态属性函数(纯)整数不纯函数(整数x,整数y)
{
a++;
返回x+y;
}
内部主(空)
{
printf(“纯函数(0,0)=%d\n”,纯函数(0,0));
printf(“不纯函数(0,0)=%d\n”,不纯函数(0,0));
返回0;
}
我用
gcc-O2-Wall-Wextra
编译了这个程序,希望用
\uuuuu属性(pure))
装饰
不纯函数()。但是,我没有收到任何警告或错误,程序运行时也没有问题

\uu属性((pure))
标记
不纯函数()
是否不正确?如果是这样,为什么即使使用
-Wextra
-Wall
标志,它也能编译而没有任何错误或警告


提前谢谢

纯函数是对函数的提示。可能,
gcc
在只传递
-O0
给它时并不关心纯函数(默认优化)。因此,如果
f
是纯的(并且在您的外部定义,例如在某个外部库中),GCC编译器可能会优化
y=f(x)+f(x)编码为类似

{ 
  int tmp = f(x); /// tmp is a fresh variable, not appearing elsewhere
  y = tmp + tmp;
}
但是如果
f
不是纯的(这是通常的情况:想想
f
调用
printf
malloc
),这样的优化是被禁止的

像or这样的标准数学函数是纯函数(除了IEEE舍入模式的疯狂,请参阅和了解更多),它们足够复杂,可以进行计算,从而使此类优化值得

您可以使用
gcc-O2-Wall-fdump tree all
编译代码,以猜测编译器内部发生了什么。您可以添加
-fverbose asm-S
标志以获得生成的
*.S
汇编文件

您也可以阅读(尤其是第§1.4节)。它可能会给你一些与你的问题相关的直觉

在您的特殊情况下,我猜
gcc
是您的调用;那么纯度就不那么重要了

如果你有时间花,你可以考虑写自己的东西来发出这样的警告。你要花几个月的时间来写它!幻灯片可能仍然对您有用,即使细节已经过时

在理论层面上,要意识到。其结果是,纯函数的完美优化可能是不可能的


请注意位于孟买的属性。

这样做是不正确的,您有责任正确使用该属性

看看这个例子:

static __attribute__((pure)) int impure_function(int x, int y)
{
        extern int a;
        a++;
        return x + y;
}

void caller()
{
    impure_function(1, 1);
}
GCC(使用-O1)为函数调用方生成的代码是:

caller():
        ret
如您所见,
inpure_函数
调用被完全删除,因为编译器将其视为“pure”

如果GCC看到函数的定义,它可以在内部自动将函数标记为“纯”:

static __attribute__((noinline)) int pure_function(int x, int y)
{
        return x + y;
}

void caller()
{
    pure_function(1, 1);
}
生成的代码:

caller():
        ret
因此,在编译器可见的函数上使用此属性没有意义。它应该在定义不可用时使用,例如在另一个DLL中定义函数时。这意味着,当它在适当的位置使用时,编译器无论如何都无法执行健全性检查。因此,实施警告不是很有用(尽管不是毫无意义)


我不认为有任何东西会阻止GCC开发人员实现这样的警告,除了必须花费的时间。

您告诉编译器,其他函数应该进行优化,就好像不纯净的函数是纯函数一样。即使函数不是纯函数,这也是有意义的,因为例如,你不关心副作用。这个属性不是编译器要检查的,它是程序员告诉编译器的,假设它不能自己推断出来。因此,你基本上是在对它撒谎,如果编译器没有根据这个谎言对它进行优化,那将是幸运的。可能是因为他们认为不值得花时间实现这样的警告。您试图自己实现一个,因为GCC是开源的。@EugeneSh。如果我正确理解您的评论,编译器会忽略该属性,并且不会优化
不纯函数()
?@AbhishekChakravarti该属性的文档没有说明此案例的行为,因此我无法确定它是否被视为“建议”只有这样,否则它会相信这是真的。谢谢你的回复。我喜欢它,并且把它投了更高的票。然而,由于提供的参考资料,我接受了Basile Starynkevitch提供的答案。再次感谢!感谢您的回答和提供的参考资料。