2010-02-23 53 views
28

當我第一次被介紹給C時,我被告知總是在函數的頂部聲明我的變量。現在我對語言有了很強的把握,我將重點放在編碼風格上,特別是限制了我的變量範圍。我已閱讀了限制範圍的好處,並且我遇到了一個有趣的例子。顯然,C99可以讓你做到這一點...我在哪裏可以合法地在C99中聲明一個變量?

for (int i = 0; i < 10; i++) 
{ 
    puts("hello"); 
} 

我原本以爲變量的作用域是由周圍花括號{ }最內側限制,但在上面的例子中int i出現在被限制範圍由for循環的花括號包括,即使它是在它們之外聲明的。

我試圖擴展上面的例子fgets()做我認爲是類似的東西,但這兩個都給了我一個語法錯誤。

fgets(char fpath[80], 80, stdin); *見注**

fgets(char* fpath = malloc(80), 80, stdin);

所以,只要在那裏它到底是合法的,在C99聲明變量? for循環示例是規則的例外情況嗎?這是否也適用於whiledo while循環?

*注**:我什至不知道這將是語法正確,即使我能聲明字符數組,因爲fgets()正在尋找字符指針字符指針的陣列80 。這就是我試用malloc()版本的原因。

+1

不管它是否合法,你都不應該這樣調用malloc,因爲你沒有檢查它是否返回NULL,也不能釋放你正在分配的堆內存,因爲fpath會立即超出範圍。 – Jeff 2015-01-01 22:06:05

回答

31

在C99中,您可以在需要它們的地方聲明變量,就像C++允許您那樣做。

void somefunc(char *arg) 
{ 
    char *ptr = "xyz"; 
    if (strcmp(arg, ptr) == 0) 
    { 
     int abc = 0; /* Always could declare variables at a block start */ 

     somefunc(arg, &ptr, &abc); 

     int def = another_func(abc, arg); /* New in C99 */ 
     ...other code using def, presumably... 
    } 
} 
  • 您可以在一個控制部分聲明一個變量「for」循環:

    for (int x = 0; x < 10; x++) /* New in C99 */ 
    
  • 你不能在一個「而」循環的控制部分或聲明一個變量'if'語句。

  • 您不能在函數調用中聲明變量。
  • 很顯然,你可以(也總是可以)在任何循環或'if'語句之後聲明塊中的變量。

C99標準表示:

6.8.5.3 for語句

聲明

for (clause-1 ; expression-2 ; expression-3) statement 

的行爲如下:表達式表達-2是被評估爲 的控制表達式是在循環體的每次執行之前。表達式-3是 ,在循環體的每次執行後評估爲空表達式。如果子句-1是一個 聲明,則它聲明的任何變量的作用域是整個循環的聲明和 的其餘部分,包括其他兩個表達式;在控制表達式的第一次評估之前按照執行 的順序達到。如果子句-1是一個表達式,那麼在對控制表達式進行第一次評估之前,將其作爲空表達式求值爲 。

+0

感謝您的詳細評論和參考標準 – SiegeX 2010-02-23 21:51:45

8

我注意到的第一件事是,你不應該混淆

for (int i = 0; i < 10; i++) { 
    puts("hello"); 
} 

fgets(char* fpath = malloc(80), 80, stdin); 

第一個是控制結構,而第二個是一個函數調用。控制結構以與函數調用不同的方式評估parens()中的文本。

第二件事是...我不明白你想說由什麼:

編譯器會及時給你一個錯誤,如果您嘗試使用我的for循環中身體。

您爲for循環列出的代碼是C中非常常見的結構,變量「i」實際上應該在for循環體中可用。即,以下應該工作:

int n = 0; 
for (int i = 0; i < 10; i++) { 
    n += i; 
} 

我誤讀你在說什麼?

+0

不,你沒有誤讀,但顯然我閱讀了一些關於我在我的問題中發佈的SO鏈接的不正確信息,該鏈接表示它不會編譯。顯然,如果沒有將-std = c99傳遞給'gcc',它就會失敗。您能否提供一些關於控制結構中的文本評估和函數調用的更多見解,因爲我認爲這絕對是我的問題試圖解決的問題的根源。 – SiegeX 2010-02-23 21:38:56

+0

您鏈接到的問題發佈了一個for循環的例子,其中包含邏輯錯誤(注意for循環結尾的分號),因爲該邏輯錯誤而無法編譯。這是一個常見的錯誤,有很多關於SO的問題。 – nos 2014-05-30 15:41:50

2

關於您的for/fgets混淆的底線是,儘管「大括號控制範圍」在大多數情況下是C中的正確規則,但在C99中有另一個關於範圍的規則(從C++借用)在控制結構的序言中聲明的變量(即for,while, if)位於結構體中(且不在體外)。

+2

顯然這隻適用於'for'循環,但+1的答案。 – SiegeX 2010-02-23 21:59:37

+1

糟糕。它適用於C++中的「if」和「while」,所以我想我認爲C99會借用整個事情,而不僅僅是「for」部分。 – 2010-02-23 23:24:54

相關問題