編輯:我沒有注意到這一點,當我寫了原來的答覆(見下文)。您發佈的代碼是非法的,並導致未定義的行爲。有問題的行是這樣的一種:
char *x = strchr(x,' ');
這裏strchr
呼叫不指在封閉範圍所限定的x
內x
,而是在同一行前面定義的x
。因此該行讀取未初始化的變量,這會導致未定義的行爲。從C++標準,
§3.3.2/ 1 [basic.scope.pdecl]
一個名字的點聲明的立即是其完整的說明符後(第8章)和其前初始化程序(如果有的話),除非如下所述。 [例如:
int x = 12;
{ int x = x; }
這裏第二個x用它自己的(不確定)值進行初始化。末端示例]如果在下面的示例中的相應行被改變爲
int x = 21 + x; // generates "warning: x is used uninitialized in this function"
,複製上VS2012您strchr
例如
GCC不抱怨生成此警告(在/W1
及以上):
warning C4700: uninitialized local variable 'x' used
原來的答案如下(不完全準確):
也沒什麼可說的代碼是非法的。您通過添加大括號來引入新範圍,並且您可以在新範圍內定義變量,即使這些變量名稱之前已在封閉範圍內定義過。
在新定義之後,所有對變量的引用都將引用局部變量而不是封閉範圍中的變量,直到本地變量的生存期結束。
42
21
42
我不知道棉絨或其他靜態分析工具是否會要麼挑選出這樣的事情:即使與-pedantic -Wall -Wextra
#include <iostream>
int main()
{
int x = 42;
{
std::cout << x << '\n';
int x = 21;
std::cout << x << '\n';
}
std::cout << x << '\n';
}
輸出編譯下面的代碼產生的GCC沒有任何警告。這是合法的,但不可取。
GCC做這個AFAIR更好... –
它們是相同的範圍沒有。一個'x'是函數範圍,一個是塊範圍。 –
我認爲這不容易引起警告。很多時候,這是人們想要的東西(例如,正式的參數名稱和類成員 - 通常你不想發明新的名字) – Ghita