假设我们在这些方面有一些东西
int f(int n);
...
do{
int a = b;
int b = f(a);
}
有没有风险说
do{
int b = f(b);
}
相反,假设a不在其他地方使用?做前者会更符合风格吗?
答案 0 :(得分:3)
重要的是要明白,你不是在改变任何变量,只是改变名称的含义。
重要的概念称为point of declaration。
让我们来看看你的例子:
int b = 42;
{
int a = b;
int b = 23 * a;
printf("%d\n", b);
}
printf("%d\n", b);
或
int b = 42;
{
int b = 23 * b;
printf("%d\n", b);
}
printf("%d\n", b);
名称b引用两个对象,具体取决于您在代码中的位置,我们称之为b1和b2。在案例1中这并不奇怪:
int b1 = 42;
{
int a = b1;
int b2 = 23 * a;
printf("%d\n", b2);
}
printf("%d\n", b1);
由于在C语言中,声明点在初始化程序之前是,因此第二个示例的解析方式不同:
int b1 = 42;
{
int b2 = 23 * b2;
printf("%d\n", b2);
}
printf("%d\n", b1);
请注意,这里b1和b2之间没有链接,你用其自己的(未定义的)值初始化b2。一个勤奋的编译器会警告你这个,比如
x.c:7:13: warning: 'b' is used uninitialized in this function [-Wuninitialized]
答案 1 :(得分:1)
当编译器解析C代码时,它会填充一个符号表,该表包含有关所有不同符号的信息,并且按符号表示标识符,例如您为变量,函数等提供的名称......
大多数C程序都是由嵌套作用域构成的,全局 - >功能 - > component_statements等等,每个作用域通常都有自己的符号表,因此编译器使用一堆符号表来跟踪所有内容,当查找变量但未在当前符号表中定义它开始搜索时向上移动堆栈直到它到达全局或通常是最后一个表...但是在当前作用域中定义了一个条目后,条目将“遮蔽”前一个。
这是一个简单的程序来说明。
#include <stdio.h>
/* global accessable by most things ... */
int a = 5;
int main()
{ /* function scope */
int a = 4; /* shadowing global */
{ /* nested scope within function scope */
int b = a;
int a = b; /* shadowing function */
printf("%i\n", a);
}
return 0;
}
如果你运行这个,你会得到4
这是预期的,但任何关注你代码的人都必须牢记a
与其他a
不同#include <stdio.h>
/* global accessable by most things ... */
int a = 5;
int main()
{ /* function scope */
int a = 4; /* shadowing global */
{ /* nested scope within function scope */
int a = a; /* shadowing function, but not actually accessing outer scope */
printf("%i\n", a);
}
return 0;
}
从全局,函数main ...如果维护代码的程序员不知道这些事情或你自己忘记了那么你可以有一些微妙的运行时错误,这些错误很难调试...
还要注意,如果你运行这个:
1606422610
你不会得到4但是我的机器上有一些大的随机int {{1}}因为变量被分配给它本身只是阴影,而c不会初始化变量。