编辑:当我写原始答案时(如下),我没有注意到这一点。您发布的代码是非法的,并导致未定义的行为。违规行是这一行:
char *x = strchr(x,' ');
这里的x
调用strchr
不是指在x
封闭范围内定义的,而是x
指在同一行之前定义的。因此,该行从未初始化的变量中读取,这会导致未定义的行为。根据 C++ 标准,
§3.3.2/1 [basic.scope.pdecl]
名称
的声明点紧接在其完整声明符(第 8 条)之后和其初始化程序(如果有)之前,除非下文另有说明。[ 例子:
int x = 12;
{ int x = x; }
这里第二个 x 用它自己的(不确定的)值初始化。—结束示例]
如果下面示例中的相应行更改为,GCC 确实会抱怨
int x = 21 + x; // generates "warning: x is used uninitialized in this function"
strchr
并在 VS2012 上复制您的示例会生成此警告(at/W1
及以上):
warning C4700: uninitialized local variable 'x' used
原始答案如下(不完全准确):
代码没有任何违法之处。您通过添加大括号引入了一个新范围,并且您可以在新范围内定义变量,即使这些变量名称之前已在封闭范围中定义。
在新定义之后对变量的所有引用都将引用局部变量而不是封闭范围内的变量,直到局部变量的生命周期结束。即使使用以下代码编译,以下代码也不会在 GCC 上产生警告-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';
}
输出:
42
21
42
我不知道 lint 或其他静态分析工具是否会挑选出这些东西。这是合法的,但不可取。