简体   繁体   English

声明与global,local和static同名的变量

[英]declaration of variables with same name as global,local and static

I have the following code snippet and I have to analyse what the output will be: 我有以下代码片段,我必须分析输出将是什么:

#include <stdio.h>

  void f(int d);

  int a = 1, b = 2, c = 3, d = 4;

  int main(){
    int a = 5, c = 6;
    f(a);
    f(b);
    f(c);
    printf("%d %d %d %d\n",a,b,c,d);
    return 0;
  }

  void f(int d){
    static int a = 0;
    a = a + 7;
    b = a + d;
    c++;
    d--;
    printf("%d %d %d %d\n",a,b,c,d);
  }

The output I've got is as follows: 我得到的输出如下:

7 12 4 4  
15 26 5 11  
21 27 6 5  
5 27 6 4  

This really baffled me. 这真让我困惑。 I noticed that in all 3 function calls the globally declared a suffers the assignment and that in the printf() from main() body the a declared in main() is printed. 我注意到,在所有3个函数调用的全局声明a遭受分配,并且在printf()main()体的a中声明main()打印。 However, I am not sure about the behaviour of the rest of the variables. 但是,我不确定其余变量的行为。 Is this undefined behaviour or it actually makes sense? 这是未定义的行为还是实际上有意义?

int a = 1, b = 2, c = 3, d = 4; ---> Global variables --->全局变量

int main(){
    int a = 5, c = 6;         ---> Shadows the global `a` and `c`

.... ....

void f(int d){
    static int a = 0;         ---> local static variable visible only inside `f`

... ...

This is related to C's identifier scopes. 这与C的标识符范围有关。 The scope of a declaration is the region of the C program over which that declaration is visible. 声明的范围是C程序的区域,该声明在该区域中可见。 There are six scopes: 有六个范围:

  • Top level identifiers: extends from the declaration point to the end of the source program file 顶级标识符:从声明点扩展到源程序文件的末尾
  • Formal parameters in a function definiton: extends to the end of the function body 函数定义中的形式参数:延伸到函数体的末尾
  • Formal parameters in function prototypes 函数原型中的形式参数
  • Block (local) identifiers: extends up to the end of the block 块(本地)标识符:一直延伸到块的末尾
  • Statement labels 声明标签
  • Preprocessor macros 预处理器宏

What happens in your program is known as overloading of names - a situation in which the same identifier may be associated to more than one program entity at a time. 程序中发生的事情称为名称重载 - 同一标识符一次可能与多个程序实体相关联的情况。 There are 5 overloading classes in C (aka namespaces): C中有5个重载类(aka名称空间):

  • Preprocessor macro names 预处理器宏名称
  • Statement labels 声明标签
  • Structure, union and enumeration tags 结构,联合和枚举标签
  • Component names 组件名称
  • Other names 其他名称

In C, declarations at the beginning of a block can hide declarations outside the block. 在C中,块开头的声明可以隐藏块外的声明。 For one declaration to hide another, the declared identifiers must be the same, must belong to the same overloading class, and must be declared in two distinct scopes, one of which contains the other. 对于一个隐藏另一个声明的声明,声明的标识符必须相同,必须属于同一个重载类,并且必须在两个不同的作用域中声明,其中一个包含另一个。

With this in mind, in your code, local a and c hide global a and c in main() , and a in f() hides global a . 考虑到这一点,在你的代码,当地ac隐藏全局acmain()af()隐藏了全球a All other references are manipulating the global variables. 所有其他引用都在操纵全局变量。

 void f(int d){
     **static int a = 0;**
     a = a + 7;
     b = a + d;
     c++;
     d--;
     printf("%d %d %d %d\n",a,b,c,d);
   }

That's right you declared global int a and global void function f but also you have declared static variable a Whenever function has called, function is refering a variable of function. 这是正确的你声明全局int a和全局void函数f但你已经声明了静态变量a每当函数调用时,函数就是引用函数的变量。 if you want to avoid this problem, you should make a pointer of global variable, and refering a pointed address's value global variable. 如果你想避免这个问题,你应该创建一个全局变量的指针,并引用一个指向地址的值全局变量。 As you know static variable is keep their last value until end of program. 如您所知,静态变量保持其最后一个值直到程序结束。

each function's variable is exactly going to placed in "Stack" unless allocated by malloc. 除非由malloc分配,否则每个函数的变量都将完全放在“堆栈”中。 And global variable is "Heap". 全局变量是“堆”。 I am not sure but if you disassembly your program, static value a would go to stack and treated with PUSH and POP instruction. 我不确定,但是如果你反汇编你的程序,静态值a会堆叠并用PUSH和POP指令处理。

In C/C++, the identifiers in a given scope shadow the identifiers in the outer scope from the point of declaration onwards . 在C / C ++中,给定范围内的标识符从声明点开始影响外部范围中的标识符。

The following example demonstrates this: 以下示例演示了这一点:

#include <stdio.h>

const char a[] = "a";

static const char b[] = "b";

void test(const char * arg)
{
   const char c[] = "c1";
   printf("1-. a=%s b=%s c=%s arg=%s\n", a,b,c,arg);
   const char a[] = "a1";
   static const char b[] = "b1";
   // arg is present in this scope, we can't redeclare it
   printf("1+. a=%s b=%s c=%s arg=%s\n", a,b,c,arg);
   {
      const char a[] = "a2";
      const char b[] = "b2";
      const char arg[] = "arg2";
      const char c[] = "c2";
      printf("2-. a=%s b=%s c=%s arg=%s\n", a,b,c,arg);
      {
         static const char a[] = "a3";
         const char b[] = "b3";
         static char arg[] = "arg3";
         static const char c[] = "c3";
         printf("3. a=%s b=%s c=%s arg=%s\n", a,b,c,arg);
      }
      printf("2+. a=%s b=%s c=%s arg=%s\n", a,b,c,arg);
   }
   printf("1++. a=%s b=%s c=%s arg=%s\n", a,b,c,arg);
}

int main(void)
{
   test("arg");
   return 0;
}

Output: 输出:

1-. a=a b=b c=c1 arg=arg
1+. a=a1 b=b1 c=c1 arg=arg
2-. a=a2 b=b2 c=c2 arg=arg2
3. a=a3 b=b3 c=c3 arg=arg3
2+. a=a2 b=b2 c=c2 arg=arg2
1++. a=a1 b=b1 c=c1 arg=arg

This output actually makes sense. 这个输出实际上有意义。

In C/C++, the identifiers in a given scope are given preference over the identifiers in the outer scope. 在C / C ++中,给定范围中的标识符优先于外部范围中的标识符。 In this case in the function main, variables a and c will be used as local variables and rest b and d as global variables. 在这种情况下,在函数main中,变量a和c将用作局部变量,其余b和d用作全局变量。 Similarly, in the function void f(int d) , d is the passed parameter, a will be used as static whenever the function is called, b and c will be used as global variables. 类似地,在函数void f(int d) ,d是传递的参数,每当调用函数时,a将用作静态,b和c将用作全局变量。 Hence the output will be calculated. 因此将计算输出。

However you have shown the incorrect output. 但是,您显示的输出不正确。 Correct output must be : 正确的输出必须是:

7 12 4 4 14 26 5 11 21 27 6 5 5 27 6 4

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

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