我遇到的代码类似于下面的代码,这是合法的,虽然不是很聪明。同一个函数中具有相同名称的同一函数中的两个堆栈变量是合法的,但它可能会导致问题。 (阅读:我浪费了半个小时来调试这个)。在VS2010(最高级别)的警告级别4,我希望它会抓住这种事情。我是否遗漏了一些东西,或者是时候用lint一次性打到整个代码库了?像lint这样的静态分析工具是否会像这样发起名称冲突?
char *x = strchr(Buffer,' ');
if (x)
{
*x = 0;
x++;
char *x = strchr(x,' ')
if (x)
*x = 0;
}
答案 0 :(得分:2)
编辑:当我写下原始答案(下方)时,我没有注意到这一点。您发布的代码是非法的,并导致未定义的行为。违规行是这一行:
char *x = strchr(x,' ');
此处x
调用中的strchr
不引用封闭范围中定义的x
,而是x
定义的 int x = 12;
{ int x = x; }
以前在同一条线上。因此,该行从未初始化的变量读取,这导致未定义的行为。从C ++标准,
§3.3.2/ 1 [basic.scope.pdecl]
名称的声明紧跟在其完整的声明符(第8条)之后和初始值设定项之前(如果有的话),除非如下所述。 [例如:int x = 21 + x; // generates "warning: x is used uninitialized in this function"
这里第二个x用它自己的(不确定的)值初始化。 - 例子]
如果以下示例中的相应行更改为
,GCC会抱怨strchr
在VS2012上复制您的/W1
示例会生成此警告(位于warning C4700: uninitialized local variable 'x' used
及以上):
-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
输出:
{{1}}
我不知道lint或其他静态分析工具是否会选择这样的东西。这是合法的,但不可取。
答案 1 :(得分:2)
PC-Lint会检测到这一点。以下代码:
main (int argc, char *argv [])
{
char *x = 0;
if (x)
{
char *x = 0;
}
}
发出警告:
main.cpp 6 Warning 578: Declaration of symbol 'x' hides symbol 'x' (line 3)