2015-02-09 64 views

回答

6

实施例:

// Declaration: 
int square (int x) __attribute__ ((const)); 
// Definition: 
int __attribute__ ((const)) square (int x) 
{ 
    return x*x; 
} 

的语法的所有属性是非常相同:__attribute__ ((<attribute-name>)),或__attribute__ ((<attribute-name> (<attribute-options>)))。从您链接到的文档中引用:

关键字__attribute__允许您在进行声明时指定特殊属性。该关键字后面跟着一个双括号内的属性规范。

有您链接到其他几个属性的文档中的例子,包括pure

int square (int) __attribute__ ((pure)); 

因此,所有你需要的,语法的角度来看,使用const,是改变pureconst

int square (int) __attribute__ ((const)); 

正如在评论中指出:如果你在一个定义使用它,那么你需要把__attribute__ ((const))在不同的位置:

int square (int) __attribute__ ((const)) { ... } // doesn't work 
int __attribute__ ((const)) square (int) { ... } // does work 

constpure属性是几乎唯一有用如果它们适用于外部声明,那么这应该不成问题。如果定义可见,GCC通常可以在没有您的帮助的情况下确定该功能是否可以被视为const/pure

5

根据本this article,语法与@hvd说什么相匹配:

int square (int) __attribute__ ((pure)); 

然而,似乎gcc当我编译下面的例子并不强制不检查全局状态的财产。

#include <stdio.h> 

int square (int) __attribute__ ((pure)); 

int outerX = 7; 
int square(int x) { 
    return outerX * x; 
} 

int main(){ 
    printf("%d\n", square(5)); 
    return 0; 
} 

以下打印没有错误,代码运行并产生35

gcc -Wall -Werror -pedantic -O3 Pure.c 


gcc --version 
gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 

更奇怪的是,gcc也没有,如果我们发生变异函数内部的全局状态和每个调用返回,因为它在全球所引起的状态变化的不同值在意。

#include <stdio.h> 

int square (int) __attribute__ ((pure)); 

int outerX = 7; 
int square(int x) { 
    outerX++; 
    return outerX * x; 
} 

int main(){ 
    printf("%d\n", square(5)); 
    printf("%d\n", square(5)); 
    printf("%d\n", square(5)); 
    return 0; 
} 

输出:

40 
45 
50 
+0

是的,文档有点误导我认为:函数是否纯粹取决于它的功能,而不是它是如何实现的。如果函数是纯粹的,即使它读取全局变量(例如,因为这些变量永不改变),那么它可能被声明为纯粹的。因此,编译器不能强制执行该属性。 – hvd 2015-02-09 09:01:02

+0

它仍然是有意义的,你的编辑:'纯粹(无效)__attribute __((纯)); int pure(void){static bool pureInited = false; static int pureValue;如果(!pureInited){pureValue = ...; pureInited = true; }返回pureValue; }'我认为可以在那里应用'pure'属性,即使函数使用静态存储持续时间来修改变量:效果仍然是该函数始终返回完全相同的值。 ('const'也可能在这里有意义,而不是'pure')。 – hvd 2015-02-09 09:08:38

+0

@hvd,你认为如果函数在每次调用时都返回不同的值并且参数相同,编译器就会大声嚷嚷? – merlin2011 2015-02-09 09:10:43

1

从C++ 11开始,可以使用attribute specifier sequence来指定这些属性。例如:

[[ gnu::const ]] 
int square (int x) 
{ 
    return x * x; 
} 

另外,从C++ 17开始,编译器未知的所有属性都会被忽略而不会导致错误。所以上面的代码可以在不同的编译器和平台之间移植。