欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c语言变量的初始化和赋值的区别

程序员文章站 2024-02-18 16:19:28
...

原理

顺着这个思路想了一下,为什么C语言的全局变量(global)就算不赋值会被自动初始化位默认值,但是局部变量(local)不会呢? 学习了一下C语言的内存布局结构,然后自己验证了一下然后明白了这个原因。

首先我们得知道C语言的内存布局结构,这篇文章 Memory layout of c program 讲的非常详细。这里列出我要用到的部分,首先看结构(图片来自这篇文章):

c语言变量的初始化和赋值的区别

从这篇文章里面我明白了两点:

  • 全局变量是存放在data段内存的。data段分为uninitialized data(bss)段和initalized data,未初始化的变量是放在bss段的,这部分内存存放的变量是会被自动初始化的(这是C语言的特性)
  • 局部变量是存放在stack段的。这部分内存是被runtime时期动态分配的。(其实局部变量在代码编译之后就是一个地址,接下来会演示出来)

明白了这两点,那我通过一个demo来验证一下是否在内存中真的是这个样子。

//test_c_variable_init.c

#include <stdio.h>

int global_var;

int main()
{
    int local_var;
    
    local_var = local_var + 3;
        
    printf("global_var: %d & local_var: %d \n", global_var, local_var);
    
    return 0;
}

利用demo里面声明的一个全局变量(global_var)和局部变量(local_var)来验证现在的问题。(对local_var加常量3的操作仅仅是为了能够快速定位local_var在反编译代码中的位置)

首先可以通过linux的size命令查看总的内存分布

编译test_c_variable_init.c文件

gcc -o test_c_variable_init test_c_variable_init.c

得到可执行文件test_c_variable_init,现在可以查看到这个可执行文件的内存分布:

c语言变量的初始化和赋值的区别

然后我们在test_c_variable_init.c中增加一个全局变量:

int global_var2;

按照之前的步骤我们再次查看重新编译的文件的内存分布:

c语言变量的初始化和赋值的区别

可以看到bss段增加了4kb,这个大小就是我们增加的global_var2变量的大小。按照同样的方式增加local_var2我们会发现data和bss段都不会增加。这样可依初步确定上面列出的两点结论了。

然后我们通过查看反编译代码直接来查看变量在编译之后的位置,这样就明确之前的两点结论。

objdump -D test_c_variable_init > test_c_variable_init.d

我们把反编译之后的代码重定向到test_c_variable_init.d文件,然后我们查看下这个文件,其中有两个地方可以让我们得到想要的答案。

这是反编译之后的main函数:

c语言变量的初始化和赋值的区别

可以看到347行的 $0xc ,之前我列出demo的时候为local_var特地添加了一个加常量3的操作,通过这个操作我可以很快定位到了$0xc 就是对应的local_var变量了, $0x3 就是常量3(addl就是汇编里面的加运算)。这里证明了local_var是分配在stack区的。此外我们注意到 0x804a020 这个地址其实就是global_var变量了,跳转到这个地址

c语言变量的初始化和赋值的区别

可以很清楚的看到 0x804a020 就是global_var并且存放在bss段的。

这样我们就验证了上面的两点结论了,也知道了为什么未初始化的全局变量会被自动初始化位默认值,局部变量不会被初始化了。







一般变量看不出什么区别,对于静态变量就很明显了,如:


int func()
{
static int a = 10; //初始化
static int b;
b = 10; //赋值
a++;
b++;
printf("%d\n", a); //第一次调用函数func,a 的值为 11,第二次调用时为 12,……
printf("%d\n", b); //第一次调用函数func,b 的值为 11,第二次调用时为 11,……
}
从上例可以看出,静态变量只初始化一次,所以 a 的值会随调用的次数递增;而 b 由于重新赋值,所以他的值始终是 11。

上一篇: 快应用开发系列(一)

下一篇: