2015-09-03 140 views
24

我在編碼時遇到了這種奇怪的行爲。所以我在這裏問。變量聲明中'for'循環的範圍

聲明變量時for循環的範圍是什麼?

此代碼編譯細

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

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

這意味着二者int i不在同一範圍內。

但是這段代碼不能編譯。

for (int i = 0; i < 10; i++) { } 
int i; // Conflicts with both first loop and second one. 
for (int i = 0; i < 10; i++) { } 

這意味着在循環的中間int i具有第一環路和第二環路的相同範圍。

int i如何能在兩個for循環有不同的範圍,但與中間相同的範圍int i?因爲目前我看到他們在同一水平。

我知道第二個代碼不能編譯。爲什麼第一個代碼會在範圍有問題時編譯呢?這是編譯器內部的異常嗎?

+1

它不在相同的範圍內,而是在嵌套的範圍內,這也是禁止的。看看這個問題的答案類似的問題:https://stackoverflow.com/questions/6156449/why-cant-a-duplicate-variable-name-be-declared-in-a-nested-local-範圍 – Dirk

+2

有趣的是,for(int i = ...){} {int i; } for(int i = ...){}'(note inner {}')does complie。 –

+1

@DmitryBychenko:這是因爲我只存在於大括號(for循環之間)所定義的塊內。 – Piters

回答

24

C#編譯器不檢查變量是在另一個變量之前還是之後被聲明的。所有重要的是範圍。在循環之間聲明的變量i肯定會與第二個循環衝突,因爲如果在循環中使用i,則無法區分您想要使用哪個i。至於第一個循環,仍然會顯示一個錯誤,因爲聲明瞭i的塊也是第一個循環。

例如,下面將無法編譯,即使j沒有內部括號外可見的,所以不應該有關於i任何含糊之處:

{ 
    { 
     int i = 1; 
     int j = 1; 
    } 

    int i = 0; // compiler error: A local variable i cannot be declared in this scope (...) 
    // j is not visible here 
} 

有關評論編輯

爲什麼以下罰款?

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

在聲明for循環變量,它是可見只在循環塊內。這意味着兩個變量的範圍是不相交的,因爲沒有一行代碼在一個塊與另一個塊「重疊」。

+1

是的。確定它與第二個循環衝突,但是這個也不會編譯。 'for(int i = 0; i <10; i ++){}' 'int i;'。 (int i = 0; i <10; i ++){}'是可能的嗎? –

+2

@ M.kazemAkhgary正如大多數答案所解釋的那樣,變量*的範圍不是以它的聲明開始,而是整個塊。 for循環定義了一個塊 –

+0

感謝您的回答。所以它就像'{int i; } {int i; '這是可能的。 –

2

沒有什麼奇怪的事情發生。在第二種情況下,您已經定義了外部i然後嘗試在每個循環中重新定義它。

for聲明聲明的變量本地環路,但你已經在外部範圍相同的名稱定義的另一個變量。

我想你已經提出了另一個範圍問題,假設變量的範圍從聲明的角度開始?

甲變量的範圍是在其中定義它的塊時,它不會受到它的位置。雖然編譯器將拒絕在聲明之前使用該變量,但它仍在範圍內

+1

其實OP的代碼與第一個for循環相沖突,你沒有解釋任何有關它的內容。 – Shaharyar

+0

@Shaharyar實際上,我做了 - 我寫了關於內部和外部循環,而不是第一或第二。外部與*兩個*循環衝突。評論他們中的任何一個,你會發現你仍然有衝突。這就是爲什麼我*沒有指定一個或另一個循環。 –

+0

從某種意義上說,變量在聲明之後纔是「範圍內」。在聲明它之前,你不能使用'i'。這種行爲可能是編譯器團隊最簡單的實現。儘管編譯器很辛苦,所以我不會責怪他們。 – RubberDuck

2

我認爲這不重要,你把int i;放在哪裏。

編譯器首先掃描字段,之後它開始掃描表達式。它不會編譯,因爲i已被識別爲字段。

1

int i;您在循環的外部聲明可用於當前函數。要麼只聲明外部int i,要麼從兩個循環中刪除int i,要麼只刪除該外部變量。

3

for循環中聲明的變量只在循環塊的範圍內,但是當你在for循環外部聲明一個變量時,for循環中不能有相同的名稱變量,因爲它會讓編譯器意識到你指的是哪個變量循環體。

就像我將你的代碼,例如:

int i =0; 
for (int i = 0; i < 10; i++) 
{ 
    i = i+1; // now compiler is confused which i you mean here, so i complains on compile time that you have two with same name 
} 

所以,如果你的循環之間聲明它像你一樣,變i在兩個for循環的範圍,因此在這兩個for循環訪問,因此,如果刪除第一個循環還是會抱怨,因爲外循環變量的全局範圍:

for (int i = 0; i < 10; i++) 
{ 
    i = i+1; // now compiler is still confused which i you mean 
} 
int i =0; 
+0

事實並非如此,你弄錯了。 OP表示它與第一個循環中的「i」聲明相沖突。你應該嘗試編譯OP的代碼。 – Shaharyar

+1

'for(int i = 0; i <10; i ++){} int i = 20;'爲什麼編譯器會混淆? – Praveen

+0

,因爲我們有兩個變量,第二個是全局的,所以它的範圍也在循環內 –

7

的for循環範圍,for(INIT; COND; INCR) { BLOCK }是在劃定範圍,以

相同
{ 
    INIT; 
    while (COND) { 
     BLOCK; 
     INCR; 
    } 
} 

因此for循環可以象兩個嵌套的範圍的最好的思想。 (注:從for上述轉換while不能正確捕捉continue的行爲。然而,這個問題是沒有專注於這一點。)

運行與int i外問題的for循環是什麼稱爲「陰影」。在C++中,如果你聲明一個範圍變量與外部範圍中的某個變量名稱相同,那麼你就「隱藏它」,默默地覆蓋它,直到範圍結束。當他們開發C#時,他們覺得這太不直觀,而且容易出錯。在C#中,從外部作用域映射變量是一種語法錯誤。通過將int i引入到外部示波器中,現在for循環自行介紹它現在是非法的。

+0

偉大的工作提到了替代範圍。我想在我的答案中包含這些細節,但我不記得'for'可以被翻譯成多少。 – Kapol