2017-08-06 66 views
5

我想使用if-else初始化一個const變量。
例如:爲什麼C不支持使用if-else語句來初始化const變量?

const int foo; 
if (bar) { 
    foo = 1; 
} else { 
    foo = 2; 
} 

在Java中,這是合法的代碼(使用的final代替const)。原因在於,在所有可能的結果中,該變量被分配一次並且不會被重新分配。在C中,這不是合法代碼。它在C中不能成爲合法代碼的原因是什麼?

const int foo = bar ? 1 : 2;

注意的是,如果foo不是自動變量,則初始化表達式必須是安倍進行評估:

+0

因爲初始化'const'發生在定義點,並且由編譯器執行。而在運行時執行'if'語句之後,所有變量都已定義。 – Peter

+1

請注意'foo = 1;'不是_initialization_。它是_assignment_,即使這是第一次在這裏賦予'foo'值。 'int foo = 42;'是_initialization_的一個例子。 – chux

+0

@jhourback我試圖解釋爲什麼這是不可能的,我理解它的方式。請看看我的編輯。 – PSkocik

回答

6

您可以使用三元運算符,但請記住,對於具有靜態或線程本地存儲類對象的初始化表達式必須是一個編譯時間常數:

const int bar = 42; 
#define BAR 42 

#if 0 
    const int foo = bar ? 1 : 2; /*ERROR -- bar is not an integer constant */ 
#else 
    const int foo = BAR ? 1 : 2; 
#endif 

void fn(void) 
{ 
    const int foo = bar ? 1 : 2; 
#if 0 
    static const int stc_foo = bar ? 1 : 2; /*ERROR*/ 
#else 
    static const int stc_foo = BAR ? 1 : 2; 
#endif 
} 

的原因是if-else語句不能用於初始化,因爲允許它需要對C語法進行一些相當廣泛的更改,並且可能會使C語法和語義更加複雜。

基本上,而不是簡單地具有以驗證該聲明符之後是=initializer表達並且該初始化表達式是一個常數,編譯器將不得不記住每個靜態/線程局部變量還沒有被初始化,然後查找無條件執行的編譯時可評估分支,並將其分配給它並用於初始化。

此外,必須允許在文件範圍內聲明(語句在當前C語法中不允許在文件範圍內),並且對限制寫入translation-unit-local全局變量的constness和內存訪問進行驗證。或者,它們可以隱式轉化爲全局構造函數,但是這會引入其他問題,例如編譯單元之間的構造函數排序(如果構造函數的生成是隱式的,將很難解決),需要實現在第一個時候支持全局構造函數地點,或靜態變量分配的當前相當簡單的性能特徵的模糊。

+1

最終的完整答案。我還要補充說,帶有靜態存儲的cont變量將被放置在RODATA段中 - 在許多系統中,它們將受到MMU的保護(或將被放置在uC的閃存中)。自動'const'變量存儲在堆棧或uP寄存器中,如果存儲在堆棧中,則不會受到意外寫入的保護。 –

16

可以由三元運算來有條件地初始化foo可變在編譯時,否則不會編譯。

+2

但只有當'foo'是一個'自動變量'。否則編譯錯誤 –

+5

@PeterJ - 不是,不。 [更有趣的例子](http://ideone.com/zj6DuO) – StoryTeller

+0

@StoryTeller - no - 在這個例子中,賦值是常量。由編譯器評估。非常糟糕的例子。當點擊鏈接 –

3

在C中,const使變量只讀

您只能在聲明時初始化const變量,而不是在此之後,因爲它變爲只讀。

這就是爲什麼你的代碼在C中不合法,因爲你正在更新一個只讀變量的

希望它會幫助!

相關問題