假设我们有一些类似的东西
int f(int n);
……
do{
int a = b;
int b = f(a);
}
有没有风险说
do{
int b = f(b);
}
相反,假设 a 没有在其他地方使用?做前者在风格上会更可取吗?
假设我们有一些类似的东西
int f(int n);
……
do{
int a = b;
int b = f(a);
}
有没有风险说
do{
int b = f(b);
}
相反,假设 a 没有在其他地方使用?做前者在风格上会更可取吗?
重要的是要了解,您不是在此处“更改”任何变量,而只是更改名称的含义。
重要的概念称为声明点。
让我们看看你的例子:
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]
当编译器解析 C 代码时,它会填充一个符号表,该表包含有关所有不同符号的信息,符号是指标识符,例如您为变量、函数等命名的名称......
大多数 C 程序都是由嵌套范围构成的,全局 -> 函数 -> component_statements 等等,每个范围通常都有自己的符号表,因此编译器使用一堆符号表来跟踪所有内容,当查看变量时up 但未在当前符号表中定义它通过向上堆栈开始搜索,直到它到达全局或通常是最后一个表......但是一旦在当前范围内定义了一个条目,就会使条目“遮蔽”前一个.
这是一个简单的程序来说明。
#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
预期结果,但是任何遵循您的代码的人都必须牢记,这与全局、函数 maina
中的所有其他人都不同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;
}
你不会得到 4 但我的机器上有一些大的随机 int1606422610
因为变量被分配给它本身只是影子,并且 c 不初始化变量。