在C语言中,有多少个未初始化的局部变量?答案通常是:与编译器有关。可以但不保证初始化为0。
不确定。简而言之,它们都是严肃的形而上学的答案,这很烦人。
当有些人为您谈论编译器,C库和处理器体系结构,但他们不能为您提供重现该问题的真实场景时,此人很可能是胡说八道。实际上,这个问题本身是一个错误的问题。
如果您能说100,000个单词,我们只需要能够确定特定情况下的特定行为。当然,我们需要设计一个相对不错的实验。
在演示实际代码的行为之前,让我给出一些知识。 CPU无法识别变量,更不用说变量名了。
CPU只会从特定的存储位置获取值,或者将值存储在特定的存储位置,因此当被问到变量的值是什么时,有必要知道该变量的值存储在哪里。考虑以下代码:#include& lt; stdio.h& 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和local func2的变量b显然位于同一位置。当调用func1时,这是一个新的内存(可能在进入主A堆栈帧之前已到达此位置),a的值取决于偏移量的初始值,该偏移量对应于在此位置加载到内存中的页面的大小,具体取决于在操作系统上:操作系统可能在将页面分配给程序页面时将页面清除为零页面。
堆栈的分配不涉及C库。显然,这里不涉及C库的行为,但是malloc分配的内存涉及C库。
打印结果,a的值为0,我们认为操作系统已返回到应用程序零页面。接下来,函数在func1中将其分配给12345后返回。
接下来调用func2时,将在func1之前退出的堆栈框架位置重建堆栈框架,并且相应位置仍为12345。我没有看到func1的ret操作有一条代码指令将堆栈清除为0出于效率方面的考虑,不应有这样的指示。
再次查看test_call函数,很明显func3和func4调用没有使用相同的堆栈帧,因此,即使在func3中分配了c的值,在堆栈帧上方的func4堆栈帧的值d也不会相同。受54321的影响。
因此,c和d的初始值都保持为0.然后,初始化局部变量而不初始化局部变量,在命令级别有什么区别?这非常简单,只需用自己的眼睛看一下,再看一下未初始化的Func1中的局部变量:// int a; 00000000004005ad& lt; func1& gt :: 4005ad:55 push%rbp 4005ae:48 89 e5 mov% rsp,%rbp 4005b1:48 83 ec 10 sub $ 0x10,%rsp 4005b5:8b 45 fc mov -0x4(%rbp),%eax 4005b8:89 c6 mov%eax,%esi 4005ba:bf 90 07 40 00 mov $ 0 x400790,%edi 4005bf:b8 00 00 00 00 mov $ 0x0,%eax 4005c4:e8 b7 fe ff ff callq 400480< printf @ plt& gt; 4005c9:c7 45 fc 39 30 00 00 movl $ 0x3039,-0x4(%rbp)4005d0:c9leaq 4005d1:c3 retq查看将局部变量a初始化为2222的版本:/ int a = 2222; 00000000004005ad& lt; func1 :: 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< printf @ plt& gt; 4005d0:c7 45 fc 39 30 00 00 movl $ 0x30 39,-0x4(%rbp)4005d7:c9 Leaveq 4005d8:c3 retq仅一个instru。
