在C语言中,请记住要初始化局部变量!

在C语言中,有多少个未初始化的局部变量?答案通常是:与编译器有关。

可以但不保证初始化为0。

不确定。

简而言之,它们都是严肃的形而上学的答案,这很烦人。

但是,当有人为您谈论编译器,C库和处理器体系结构时,却无法为您提供重现该问题的真实场景,那么这个人很可能是胡说八道。

实际上,这个问题本身是一个错误的问题。

如果您能说100,000个单词,我们只需要能够确定其在特定情况下的特定行为。

当然,这需要设计一个相对可行的实验。

在演示实际代码的行为之前,让我给出一些知识。

CPU无法识别变量,更不用说变量名了。

CPU只会从特定的存储位置获取值,或者将值存储在特定的存储位置,因此当被问到变量的值是什么时,有必要知道该变量的值存储在哪里。

考虑以下代码:#include void func1(){int a; printf(“ func1:%d ”,a); a = 12345;} void func2(){int b; printf(“ func2:%d ”,b);} void func4(){int d; printf(“ func3:%d ”,d);} void func3(){int c; printf(“ func3:%d " c); c = 54321; func4();} void test_call(){func3();} int main(int argc,char ** argv){func1(); func2(); test_call();}我们从func1到func4一共有4个函数,并且内部有一个未初始化的局部变量。

它们的价值是什么?对于这种局部变量,其值取决于:变量在堆栈中的位置。

该变量对应于堆栈位置是否已存储过?如您所见,上面的第一点标记了一个内存位置,第二点是代码的行为,即只要有存储对应位置的代码,以及后面的代码(如果没有复位值)位置的位置,位置将在存储后保留原始值。

验证非常简单,请尝试:[root @ localhost test]#./a.outfunc1:0func2:12345func3:0func3:0根据函数调用堆栈框架,func1的局部变量a和局部变量的变化而定func2的变量b显然位于同一位置。

调用func1时,这是一个新的内存(也许在进入main之后,堆栈帧到达了该位置之后),a的值取决于在此位置被调用到内存中的页面的相应偏移量的初始值。

在操作系统上:将操作系统分配给程序页面时,操作系统可能会将页面清除为零页面。

堆栈分配不会涉及C库。

显然,这里不涉及C库的行为,但是malloc分配的内存涉及C库。

打印的结果显示a的值为0,我们认为操作系统已向应用程序返回了零页。

接下来,该函数将其分配给func1中的12345后返回。

当下一次调用func2时,将在以前退出func1的堆栈框架位置重建堆栈框架,并且相应位置仍为12345。

在执行func1代码指令0的ret操作后,我没有看到堆栈清除。

考虑因素,不应有此类说明。

查看test_call函数,很明显,func3和func4不是使用同一堆栈帧来调用的,因此即使将func3中的c分配给了54321,也不会影响func4在堆栈帧上方的值d 。

因此,c和d的初始值保持为0.然后,在指令级初始化局部变量而不初始化局部变量的区别是什么?这很简单,只需用自己的眼睛看一下即可。

首先看一下未初始化的局部变量的func1:// int a; 00000000004005ad:4005ad:55 push%rbp 4005ae:48 89 e5 mov%rsp,%rbp 4005b1:48 83 ec 10 sub $ 0 x10,%rsp 4005b5:8b 45 fc mov -0x4(%rbp),%eax 4005b8:89 c6 mov%eax,%esi 4005ba:bf 90 07 40 00 mov $ 0x400790,%edi 4005bf:b8 00 00 00 00 mov $ 0x0,%eax 4005c4: e8 b7 fe ff ff callq 400480 4005c9:c7 45 fc 39 30 00 00 movl $ 0x3039,-0x4(%rbp)4005d0:c9 Leaveq 4005d1:c3 retq查看局部变量a的初始化2222版本:// int a = 2222; 00000000004005ad:4005ad:55 push%rbp 4005ae:48 89 e5 mov%rsp,%rbp 4005b1:48 83 ec 10 sub $ 0x10,%rsp 4005b5:c7 45 fc 00 00 00 00 movl $ 0x0,-0x4( %rbp)4005bc:8b 45 fc mov -0x4(%rbp),%eax 4005bf:89 c6 mov%eax,%esi 4005c1:bf 90 07 40 00 mov $ 0x400790,%edi 4005c6:b8 00 00 00 00 mov $ 0 x0,%eax 4005cb:e8 b0 fe ff ff callq 400480 4005d0:c7 45 fc 39 30 00 00 movl $ 0x3039,-0x 4(%rbp)4005d7:c9 Leaveq 4005d8:c3 retq仅缺少一条指令:4005b5: c7 45 fc 00 00 00 00 movl $ 0x0,-0x4(%rbp)初始化操作由实际指令完成

产品知识/行业、品牌资讯

行业、品牌资讯