变量的多个实例(静态,非静态)

时间:2014-01-15 12:35:19

标签: c static scope

我遇到了这段C代码:

main(){
static int i=0;
i++;

if(i<=5){
      int i = 3;
      printf(" %d",i);
      main();
    }
}

1。首先,由于变量i有多个定义,我希望此代码能够提供编译错误。但是,它编译并成功运行并提供了此输出。

 3 3 3 3 3

2。观察输出, 3 正好打印5次,这意味着循环从 0到5 计算,这意味着对于 if condition ,使用i的第一个定义(静态)。

3 但是,正在打印的值为 3 ,这是i的第二个定义。

因此变量标签i指的是内存中的两个不同实例。一个用作循环计数,用于增量,另一个用于打印值。

我能以某种方式解释这一点的唯一方法是:

    每次递归调用都会重复
  1. int i = 3(第二个定义)。 i实例是在调用函数时创建的,并在下一次递归调用时被终止。 (因为静态范围)。 printf使用实例,因为它是最新的定义(?)

  2. 当输入新的递归级别时,i++正在完成。由于没有其他方法可以解析此i,因此它使用i的静态“实例”,它在代码中仍然是“活动的”,因为它被定义为静态。

    < / LI>

    然而,我无法确切地说明这是如何工作的......有人能解释一下这里发生了什么,在代码和内存中?

    编译器如何在这里完成变量绑定?

3 个答案:

答案 0 :(得分:4)

内部范围胜出。

示例:

int i = 1;
void foo() {
    int i = 2; // hides the global i

    {
        int i = 3; // hides local i
    }
}

此行为是设计使然。您可以做的是对变量范围使用不同的命名约定:

  • 全局/静
  • 函数参数
  • 当地人
  • class / struct members

如果在同一函数中隐藏变量(例如函数参数和常规局部变量),某些编译器将发出警告。所以你是编译器的最大警告级别。

答案 1 :(得分:1)

if语句{}创建新的块范围,当您在该范围内声明i时,您隐藏外部范围中的i。新范围直到{才开始,因此 if语句指的是外部范围中的i

C99标准部分草案中涵盖了隐藏6.2.1 标识符范围 4 表示(强调我的):< / p>

  

[...]如果标识符指定同名的两个不同实体   空间,范围可能重叠。如果是这样,一个实体(内部范围)的范围将是a   另一个实体范围的严格子集(外部范围)。在内部范围内,   identifier指定在内部作用域中声明的实体; 在外部范围内声明的实体在内部范围内隐藏(并且不可见)

答案 2 :(得分:1)

当存在多个该变量的变量时,编译器将始终使用变量的最本地版本

在循环之外,第一个i是唯一存在的i,因此它是被检查的那个。然后创建一个新的i,值为3.此时,只要你谈论i,它就会假设你的意思是第二个,因为那是更本地化的。当您退出循环时,第二个i将超出范围并被删除,因此如果您再次开始讨论{{1}},它将是第一个。