简体   繁体   English

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

[英]Multiple instances of a variable (static, non-static)

I came across this piece of C code: 我遇到了这段C代码:

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

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

1. First, I expected this code to give a compilation error as there are multiple definitions of the variable i . 1.首先,我希望此代码会产生编译错误,因为变量i有多个定义。 But, it compiled and ran successfully and gave this output. 但是,它编译并成功运行并给出了输出。

 3 3 3 3 3

2. Observing the output, 3 is printed exactly 5 times, which means the loop was counted from 0 to 5 thus implying that for the if condition , the first definition (static) of i was used. 2.观察输出,3被印刷恰好5倍,这意味着循环从0计数到5因此暗示了如果条件 ,先定义(静态) i使用。

3 However, the value being printed is 3 which is the 2nd definition of i . 3但是,要打印的值为3 ,这是i的第二个定义。

So the variable label i is referring to two different instances in memory. 因此,变量标签i指向内存中的两个不同实例。 One is being used as the loop count, to do the increment, and the other is the value being printed. 一种用作循环计数,进行增量,另一种用作打印值。

The only way I can somehow explain this is: 我能以某种方式解释这一点的唯一方法是:

  1. int i = 3 (the 2nd definition) is repeated in every recursive call. 在每个递归调用中都重复int i = 3 (第二个定义)。 That instance of i is created when the function is called, and killed when the next recursive call is made. 实例i当函数被调用时创建,下一个递归调用时被杀。 (Because of static scoping). (由于静态作用域)。 printf uses this instance, as it is the latest definition(?) printf使用实例,因为它是最新的定义(?)

  2. When entering a new level of recursion, i++ is being done. 当进入新的递归级别时, i++已完成。 Since there is no other way to resolve this i , it uses the static "instance" of i , which is still "alive" in the code as it was defined as static. 由于没有解决这个没有其他办法i ,它使用的静态“实例” i ,因为它被定义为静态仍处于代码“活着”。

However, I'm unable to exactly put a finger on how this works..can anyone explain what's going on here, in the code and the memory? 但是,我无法确切地指出它是如何工作的。有人能解释一下代码和内存中的情况吗?

How is the variable binding being done by the compiler here? 编译器在这里如何完成变量绑定?

The inner scope wins. 内部范围胜出。

Example: 例:

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

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

This behavior is by design. 此行为是设计使然。 What you can do is use different naming conventions for variable scopes: 您可以做的是对变量范围使用不同的命名约定:

  • global/statics 全局/静态
  • function arguments 函数参数
  • locals 当地人
  • class/struct members 类/结构成员

Some compilers will issue a warning if you hide a variable in the same function (eg function argument and regular local variable). 如果您在同一函数中隐藏变量(例如,函数参数和常规局部变量),则某些编译器会发出警告。 So you the max warning level on your compiler. 因此,您在编译器上的最大警告级别。

The {} of the if statement creates a new block scope and when you declare i in that scope you are hiding the i in the outer scope. {} if语句创建一个新的块范围 ,当你声明i在你的范围都躲在i的外部范围。 The new scope does not start until { and thus the if statement is referring to the i in the outer scope. 新的作用域直到{才开始,因此if语句在外部作用域中引用i

Hiding is covered in the draft C99 standard section 6.2.1 Scopes of identifiers paragraph 4 says ( emphasis mine ): 隐藏在C99标准草案的第6.2.1节中,标识符范围4段说( 重点是 ):

[...]If an identifier designates two different entities in the same name space, the scopes might overlap. [...]如果标识符在同一名称空间中指定两个不同的实体,则范围可能会重叠。 If so, the scope of one entity (the inner scope) will be a strict subset of the scope of the other entity (the outer scope). 如果是这样,则一个实体的范围(内部范围)将是另一实体的范围(外部范围)的严格子集。 Within the inner scope, the identifier designates the entity declared in the inner scope; 在内部范围内,标识符指定在内部范围内声明的实体; the entity declared in the outer scope is hidden (and not visible) within the inner scope . 在外部范围内声明的实体在内部范围内隐藏(不可见)

The compiler will always use the most local version of a variable when more than one variable of that name exists. 当存在多个相同名称的变量时,编译器将始终使用该变量的最新版本

Outside the loop, the first i is the only one that exists, so it is the one that is checked. 在循环之外,第一个i是存在的唯一一个,因此它是被检查的那个。 Then a new i is created, with value 3. At this point whenever you talk about i it will assume you mean the second one, since that's more local. 然后创建一个新的i ,其值为3。在这一点上,每当您谈论i ,都将假设您的意思是第二个,因为这是更本地化的。 When you exit the loop, the second i will go out of scope and be deleted and so if you start talking about i again it will be the first one. 当您退出循环时,第二个i将超出范围并被删除,因此,如果您再次开始谈论i ,它将是第一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM