【问题标题】:Multiple instances of a variable (static, non-static)变量的多个实例(静态、非静态)
【发布时间】:2014-02-03 22:23:03
【问题描述】:

我偶然发现了这段 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 条件,使用了i 的第一个定义(静态)。

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

所以变量标签i 指的是内存中的两个不同实例。一个用作循环计数,进行增量,另一个是正在打印的值。

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

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

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

但是,我无法确切说明它是如何工作的。任何人都可以解释这里发生了什么,在代码和内存中吗?

这里的编译器是如何进行变量绑定的?

【问题讨论】:

  • 你没有while 循环...
  • @user3156863 感谢您指出该错误。更正了问题。

标签: c static scope


【解决方案1】:

内部作用域获胜。

例子:

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

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

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

  • 全局/静态
  • 函数参数
  • 当地人
  • 类/结构成员

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

【讨论】:

  • 谢谢,我一直认为具有相同标识符的多个定义会产生编译错误。在打印每个定义和 1 2 3 之后,使用 printf 语句测试您的代码。
  • 同一范围内的 2 个定义是错误的。函数argemnt 与局部变量具有相同的作用域(示例中为int i = 2
【解决方案2】:

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

在循环之外,第一个i 是唯一存在的,所以它是被检查的那个。然后创建一个新的i,其值为3。此时,无论何时您谈论i,它都会假定您指的是第二个,因为它更本地化。当您退出循环时,第二个i 将超出范围并被删除,因此如果您再次开始谈论i,它将是第一个。

【讨论】:

    【解决方案3】:

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

    C99 标准草案 6.2.1Scopes of identifiers4 段提到了隐藏内容(强调我的):

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-10
    • 1970-01-01
    • 1970-01-01
    • 2022-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多