2014-09-23 15 views
0

用下面的代碼不能使用`爲getpagesize()`調用設置一個全局變量用C

#include <unistd.h> 

int a = getpagesize(); 

int main() { 
    return a; 
} 

我收到以下編譯錯誤

3:1: error: initializer element is not constant 

什麼是「初始化元素」,爲什麼它需要保持不變?這與const限定符有關嗎?

+0

嗯......那是因爲初始化函數getpagesize()不是常量。這是一個函數調用。 – Gene 2014-09-23 00:17:40

+0

編譯器無法知道'getpagesize()'幾乎總是給出相同的值(並且理論上可能會使Linux內核在其中可能發生變化,例如,對於大頁面大小的支持) – 2014-09-23 00:18:56

+0

執行程序開始於進入'main'功能。沒有時間調用getpagesize()來執行。 – 2014-09-23 00:49:23

回答

4

用於初始化全局變量的值需要在編譯時確定。函數的返回值(至少在C中)在運行時間之前不會被評估。因此,像:

int a = 4; 

是確定的,但:

int a = somefunction(); 

不是。在C++中,你可以有constexpr函數,但是在C中你不能。

如果你必須做這樣的事情,你可以隨時使用:

int a; 

int main(void) { 
    a = getpagesize(); 

    /* Rest of your program */ 
} 

顯然,你不能讓你的全球const這樣做(因爲你只能在初始化設置const變量的值,你不能用函數初始化全局變量)。坦率地說,你可能沒有理由不能在你需要時調用getpagesize(),而完全忘記一個全局變量 - 除非你稱它爲十億次,否則你不會注意到開銷。如果你必須有一個全局變量,那麼就不要使它成爲const

如果不變性是一個絕對的要求,問題是避免昂貴的函數調用,而不是完全避免函數調用,那麼一個選項是一個廉價的函數調用來取代它,像這樣:

int poor_mans_global(void) { 
    static int a = -1; 
    if (a == -1) { 
     a = getpagesize(); /* Only call the expensive function once */ 
    } 
    return a; 
} 

並撥打poor_mans_global()而不是使用您的全局變量。請注意,此示例僅用於說明,並不意味着getpagesize()是一個昂貴的函數調用。

最後的選擇是將需要訪問此全局的所有代碼打包到單獨的翻譯單元中,並創建全局文件static,即文件範圍而不是真正的全局文件。 const的好處 - 從來沒有全部很好的開始,在C - 當你可以嚴格控制哪些代碼可以訪問該變量時顯着降低。

+0

有趣,謝謝。你認爲有一種方法可以將頁面大小放入全局變量中,最好是不可變的嗎? – kdbanman 2014-09-23 00:19:57

+0

@kdbanman:見編輯回答。 – 2014-09-23 00:29:15