C/C++变量没有赋初值编译器如何处理

在给出答案之前我们先C语言编写一个程序来研究一下编译器如何对待那些没有被赋初值的变量

#include <stdio.h>
int main(void)
{
	int variable,variable_1;
	printf("values = %d  x = %d  y = %d\n",variable,variable_1);

	return 0;
}

运行结果如下:

variable = -858993460  variable_1 = -858993460

为什么会是这这个,这个值从哪里来的呢?我们带着疑问进一步研究

这里用到vc++6.0的调试器,你们用其他IDE也可以(前提是必须有debug查看汇编功能)

光标移到按下F9 int variable,variable_1;会出现一个红点表示下断点成功,程序运行到这一句就会被断下

接下来按F5开始调试程序,程序断下来后鼠标右键->go to disassembly  查看反汇编,然后我们可以看到

00401010   push        ebp
00401011   mov         ebp,esp
00401013   sub         esp,48h
00401016   push        ebx
00401017   push        esi
00401018   push        edi
00401019   lea         edi,[ebp-48h]
0040101C   mov         ecx,12h
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]    //对 ebp到 ebp - 0x48 的位置用0xcc填充
4:        int variable,variable_1;
5:        printf("variable = %d  variable_1 = %d\n",variable,variable_1);
00401028   mov         eax,dword ptr [ebp-8]        //这个[ebp-0x8]就是我们的variable_1
0040102B   push        eax                                     //c语言默认调用约定 最后一个参数第一个压栈
0040102C   mov         ecx,dword ptr [ebp-4]        //[ebp -0x4]则是我们的variable
0040102F   push        ecx                                     //c语言默认调用约定 第一个参数最后一个压栈
00401030   push        offset string "j = %.2f  k = %d  z = %d\n" (0042601c)   //最后把"j = %.2f  k = %d  z = %d\n" 压入堆栈
00401035   call        printf (004010a0)                                                           //调用printf函数
0040103A   add         esp,0Ch
6:
7:        return 0;
0040103D   xor         eax,eax
8:    }
0040103F   pop         edi
00401040   pop         esi
00401041   pop         ebx
00401042   add         esp,48h
00401045   cmp         ebp,esp
00401047   call        __chkesp (004011d0)
0040104C   mov         esp,ebp
0040104E   pop         ebp
0040104F   ret

从上面反汇编代码我们可以看出:

variable:ebp - 0x4

variable_1:ebp -0x8

知道了这一点后我们就可以查看variable跟variable_1在内存中存储的值是多少了,我们切换后vc6.0然后按F10单步跟踪到

ebp -0x8 和 ebp -0x4 的地方就可以看到variable跟variable_1在内存中存储的值了

可以看到我们两个变量在内存存储的数值都是0xcccccccc   为什么呢?

因为上面分析反汇编代码的时候我已经注释了ebp 到 ebp-0x48 的位置都会被填充位0xcc

00401019   lea         edi,[ebp-48h]
0040101C   mov         ecx,12h
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]    //对 ebp到 ebp - 0x48 的位置用0xcc填充

我们对变量进行赋初值的时候编译器会生成对应的汇编代码

例如:int variable = 10;------> mov dword ptr ds[ebp-4],0xA

只有对变量进行赋初值的时候才会修改ebp-4在内存的数值,如果不赋初值那么当我们用到这个变量的时候编译器就默认把0xcccccccc当作我们变量的初值对待。

现在搞清楚了不赋初值的问题你们是不是还有一个疑问:打印出来的是:-858993460   为什么内存显示的是0xcccccccc?

这涉及到<有符号整形的存储方式>这里就不一一解说我们用一段代码来演示一下!

#include <stdio.h>
int main(void)
{
	int x = 0xcccccccc;  //定义一个int有符号整型变量
	printf("%d\n",x);

	return 0;
}

 

编译->运行..........

0xcccccccc就是-858993460

我们让编译器把 int x; 当作有符号整型变量来使用他就是-858993460   如果我们要编译器当成无符号整型来看待呢?

#include <stdio.h>
int main(void)
{
	int x = 0xcccccccc;
	printf("%u\n",x);	//%u打印无符号整型变量
	return 0;
}

编译->运行..........

打印出来的值不再是-858993460 而是 3435973836  不管加不加unsigned变量在内存存储的数据都是0xcccccccc ,就看我们怎么使用罢了

#include <stdio.h>
int main(void)
{
	int x = 0xcccccccc;
	printf("ux = %u\n",x);
	printf("sx = %d\n",x);	
	return 0;
}

如果是定义的全局变量或者静态变量,未初始化的话就是0.如果是局部变量,那就是以前残留在堆栈里的随机值。

区分变量的类型,有两种情况。

1、局部变量。

局部变量在没有显式初始化时,其值C语言规范没做要求,可以是随机值,也可以是编译器随意给定的值。

比如gcc编译器的局部变量就是随机值,可能为任何值。而微软的编译器,如VC或VS,则会初始化为全c,即0xCCCCCCCC。

2、全局变量或静态局部变量。

      (1)所有的全局变量,即定义在函数外的变量,默认值为0。

      (2)所有的静态局部变量,即定义在函数内部的static int name形式的,默认初始化为0。

3.所以类型的变量只要不赋初值都是出现内存数据0xcccccccc的情况但是printf打印出来的内容不一样。

4.最好在变量定义的时候就对变量进行赋初值,虽然编译器可以编译过去但是会有一条警告,可以运行但是很危险。

  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值