环境
- Microsoft Visual Studio Community 2022
- Windows 11 家庭中文版
笑话
小明在超市买了3瓶汽水,他先打开第0瓶汽水,咕咚咕咚喝光了,接着打开第1瓶汽水,又咕咚咕咚喝光了,然后又打开第2瓶汽水,咕咚咕咚喝光了,然后又打开第3瓶汽水,刚喝了一口,突然喊道:“烫烫烫烫烫烫烫!”
解释
在Visual Studio中,未分配的内存空间,其初始值用 0xCC (1个字节)填充,而查询编码表可知, 0xCCCC (2个字节)代表字符 烫 。
如果转换为10进制,比如int数值,int是4个字节,也就是说,把 0xCCCCCCCC (4个字节)转换为10进制,其值是 -858993460 。
在该笑话中,小明买了3瓶汽水,假设使用的是数组,那么能访问的数组下标为0、1、2,如果访问下标3,显然越界了。
在C语言中,对字符串的处理,稍不注意,就很容易出现越界的情况,而且编译和运行可能都不会报错,所以要格外小心。具体来讲,字符串是以 \0 结尾的,也就是说,在访问字符串的时候, \0 相当于一个哨兵,找到这里,就知道字符串结束了,否则会一直找下去,产生不可预知的结果。
测试
准备
在Visual Studio中创建一个新项目,选择 Empty Project :

右键单击Source Files,Add -> New Items… ,创建 Test0527.cpp 文件:

测试1
打开 Test0527.cpp 文件,编辑如下:
#include <iostream>
using namespace std;
int main() {
char str[4];
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
str[3] = 0;
cout << str << endl;
}
这是正确的用法,要想使用字符数组来存储字符串 abc ,数组长度应该是4而不是3,最后一个元素 str[3] 要填入 \0 ,表示字符串结束。
运行程序,结果如下:

测试2
如果忘了最后需要一个 \0 ,而把字符数组的长度设置为3,则在打印 str 时,依次访问到 a 、 b 、 c 之后,并不会结束,而是会继续访问下去。如果接下来是未分配的内存空间,即 0xCCCCCCCCCCCCCCCCCCCCCCCC... ,就会出现 烫烫烫... 的字样。
修改程序如下:
#include <iostream>
using namespace std;
int main() {
char str[3];
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
cout << str << endl;
}
运行程序,结果如下:

注:本例中,数组可以直接初始化:
char str[3] = {'a', 'b', 'c'};
要想查看其int值,可以用一个int指针指向未初始化的元素,比如 str[3] (注:编译器会发现此处越界,可以使用 str + 3 指针):
int* p = (int*)(str + 3);
cout << *p << endl;
其输出结果为 -858993460 。
测试3
实际上,静态分配的内存,如果没有初始化,其初始值也是 0xCC 。
修改程序如下:
#include <iostream>
using namespace std;
int main() {
char str[3];
cout << str << endl;
}
运行程序,结果如下:

其它
动态分配且未初始化的内存
对于动态分配的内存,如果没有初始化,其初始值是 0xCD ,转换为中文字符为 屯 ( 0xCDCD ),其4字节( 0xCDCDCDCD )对应的int值为 -842150451 。
编辑程序如下:
#include <iostream>
using namespace std;
int main() {
char* p = new char[100];
p[0] = 'a';
p[1] = 'b';
p[2] = 'c';
cout << p << endl;
delete[] p;
}
运行程序,结果如下:

要想查看其int值,可以用一个int指针指向未初始化的元素,比如 p[3] :
int* p2 = (int*)(p + 3);
cout << *p2 << endl;
其输出结果为 -842150451 。
动态分配且已释放的内存
一块动态分配的内存,在释放掉之后,系统会用 0xDD 来填充。此时,如果又去访问它,则转换为中文字符为 葺 ( 0xDDDD ),其4字节( 0xDDDDDDDD )对应的int值为 -572662307 。
编辑程序如下:
#include <iostream>
using namespace std;
int main() {
char* p = new char[100];
char* p2 = p;
delete[] p;
cout << p2 << endl;
}
运行程序,结果如下:

要想查看其int值,可以用一个int指针指向 p (在释放 p 之前),或者指向 p2 :
int* p3 = (int*)p2;
cout << *p3 << endl;
上述代码放在 p 释放之后,其输出结果为 -572662307 。







![[acwing周赛复盘] 第 105 场周赛20230527](https://img-blog.csdnimg.cn/ebe525ceb0a54a02a9e8a76f48606662.png)











