1

假设我们有一些类似的东西

int f(int n);

……

do{
    int a = b;
    int b = f(a);
}

有没有风险说

do{
    int b = f(b);
}

相反,假设 a 没有在其他地方使用?做前者在风格上会更可取吗?

4

2 回答 2

3

重要的是要了解,您不是在此处“更改”任何变量,而只是更改名称的含义。

重要的概念称为声明点

让我们看看你的例子:

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]
于 2012-08-17T06:28:24.713 回答
1

当编译器解析 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 不初始化变量。

于 2012-08-17T06:30:21.907 回答