为什么局部变量不初始化,VS2013 打印出来的刚好是 -858993460?

为什么局部变量不初始化,VS2013 打印出来的刚好是 -858993460?
不知道你有没有遇到过这种诡异的事情在 Visual Studio 2013 里写了一段很简单的 C 语言代码定义了一个局部变量结果手快没给它赋初值直接 printf 打印了出来。按下 F5 运行的那一秒控制台没有弹出你期待的 0也没有报错崩溃而是黑底白字赫然写着一行巨额数字-858993460。或者更诡异的是当你打印一串字符时控制台直接刷出一排整整齐齐的“烫烫烫烫烫烫烫”。那一瞬间你甚至怀疑是不是自己的电脑 CPU 烧了或者编译器中邪了。别慌今天我们就来剥开 VS2013 的内存外衣看看这个神秘的魔鬼数字到底是怎么来的。为什么 C 语言不默认清零首先我们要明白一个最基础的常识C 语言里在函数内部定义的普通变量叫做“局部变量”。在 C 语言的设计里为了追求极致的运行速度编译器默认是不会帮你把局部变量清零的。也就是说你定义了一个int age;它在内存里占用了 4 个字节但这 4 个字节里原来装的是什么现在就还是什么。这就是所谓的“垃圾数据”或者“残留数据”。那么为什么每次我们在 VS2013 里不给变量赋初值打印出来的偏偏就一定是-858993460而不是别的数字呢难道残留数据也喜欢抱团其实这是 VS 编译器团队MSVC故意设计的一个“良苦用心”。0xCC微软开发者的特殊警告在 VS 的 Debug调试模式下编译器为了帮我们这些容易粗心的开发者揪出“未初始化变量就直接使用”的 Bug会搞一个小动作它在给局部变量分配栈内存空间时会把这片空间里所有的每一个字节全部强行填充为十六进制的0xCC。因为 0xCC 这个数据非常特殊在 x86 汇编里它代表INT 3中断指令也就是调试断点。如果你的 int 变量占用了 4 个字节不初始化时这 4 个字节在内存里连起来就是0xCC 0xCC 0xCC 0xCC。在计算机里整数是以补码形式存储的。当 printf 尝试把十六进制的0xCCCCCCCC当作一个带符号的 32 位整型数int打印出来时按照补码规则去转换最左边第一位是 1代表是个负数。对其取反再加 1 还原成原码算出来的十进制数值不多不少刚好就是-858993460懂了吧根本没有什么灵异事件这个数字是 VS 编译器在 debug 时故意塞给你的。它的潜台词其实是“喂醒醒这个变量你忘了给初值了”#include stdio.h int main() { int score; // VS2013 在Debug模式下会将其内存填充为 0xCCCCCCCC // printf(%d\n, score); // 如果强行运行就会输出 -858993460 return 0; }“烫烫烫”又是怎么回事至于为什么会打印出“烫烫烫”原理也是一模一样的。在 GBK 编码也就是我们中文 Windows 系统默认的控制台编码下两个连续的字节0xCC 0xCC凑在一起刚好对应了一个汉字——“烫”。当你定义了一个字符数组比如char names[10];却忘了在末尾加字符串结束符\0printf(%s, names);就会像一个不知疲倦的跑腿小哥在内存里一直往后找\0。它一路上经过了无数个被 VS 填充了 0xCC 的未初始化区域每经过两个 0xCC控制台上就多吐出一个“烫”字。于是你就喜提了一锅热气腾腾的“烫烫烫烫烫烫烫”。如何避坑在 VS2013 下如果你写出了这种代码其实编译器是会警告你的。如果你直接按 F5 编译运行VS2013 会直接弹出一个警告弹窗甚至直接报出error C4700: 使用了未初始化的局部变量 score强行阻止你继续犯错。这就是编译器对你最后的温柔。但有些时候如果你的代码逻辑比较复杂比如把这个未初始化的变量传给了别的函数编译器可能就查不出来了这就会导致程序在运行时出现莫名其妙的逻辑错误。避开这个深坑的唯一标准姿势就是养成定义变量时顺手初始化的好习惯。int score 0; char buf[100] { 0 };别小看这一个简单的 0它能帮你干掉开发生涯中 80% 莫名其妙的玄学 Bug。今日思考题最后给大家留个有意思的小思考如果我们在 Linux 环境下用 gcc 编译器跑这段未初始化的代码还会打印出 -858993460 吗为什么动手试一下把你的发现写在评论区我们下期见标签#C语言#内存初始化#VS2013#踩坑日记#调试技巧