2015-02-09 39 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開始,編譯器未知的所有屬性都會被忽略而不會導致錯誤。所以上面的代碼可以在不同的編譯器和平臺之間移植。