memset:字节级内存填充
核心特点
- 仅能按字节填充,因此仅适合填充「单字节值」(如
0/-1); - 填充非单字节值(如
1)会出错(因为每个字节填0x01,4 字节 int 会变成0x01010101=16843009)。
示例 1:数组清 0(最常用)
#include <cstring> // memset头文件
int main() {
int arr[5];
// 把arr的5个int(共20字节)每个字节填0
memset(arr, 0, sizeof(arr));
// arr所有元素为0
char buf[100];
// 字符数组清0(等价于buf[0]='\0',但清空整块内存)
memset(buf, 0, sizeof(buf));
return 0;
}
示例 2:填充 - 1(特殊值,字节全为 0xff)
int arr[5];
// -1的补码是0xff(单字节),填充后每个int的4字节都是0xff → 整数值为-1
memset(arr, -1, sizeof(arr));
反例(禁止):填充非单字节值
int arr[5];
第一步:先明确两个基础规则
1. int 类型的内存占用(32/64 位系统通用)
一个int变量在内存中占 4 个字节(32 位),可以把它想象成「4 个连续的小格子」,每个格子存 1 个字节(8 位)的数据。
比如定义int num;,它的内存布局是:
| 字节位置(假设) | 0x100 | 0x101 | 0x102 | 0x103 |
|---|---|---|---|---|
| 存储内容 | ? | ? | ? | ? |
2. memset 的工作规则:只认 “字节”,不认 “变量类型”
memset(ptr, c, n) 的逻辑是:
- 从
ptr指向的内存地址开始; - 把每一个字节都设置为
c(c会被转成unsigned char,即 0~255 的数值); - 一共设置
n个字节。
简单说:memset 不管你要填充的是int/char/double,它只会 “一个字节一个字节地填同一个值”。
第二步:拆解 “填充 1 出错” 的核心原因
我们以memset(arr, 1, sizeof(arr))为例(arr 是 int [5]):
1. 先看 “填充 1” 时,memset 做了什么?
memset接收的第二个参数是1,会先转成单字节值0x01(十六进制),然后给arr中每一个字节都填0x01。
2. 一个 int 元素的 4 个字节被填成了什么?
因为一个 int 占 4 字节,所以每个 int 元素的 4 个 “小格子” 都会被填0x01,内存布局变成:
| 字节位置 | 0x100 | 0x101 | 0x102 | 0x103 |
|---|---|---|---|---|
| 填充值 | 0x01 | 0x01 | 0x01 | 0x01 |
3. 这个内存布局对应的 int 值是多少?
计算机按「十六进制→十进制」解析这个 4 字节的 int:
- 十六进制整体:
0x01010101(把 4 个字节拼起来); - 转十进制:
1 + 1×256 + 1×256² + 1×256³ = 1 + 256 + 65536 + 16777216 = 16843009。
这就是为什么memset(arr, 1, sizeof(arr))后,int 数组的元素不是 1,而是 16843009!
第三步:对比理解 “0/-1 填充正常” 的原因
1. 填充 0(memset (arr, 0, sizeof (arr)))
每个字节填0x00,int 的 4 个字节都是0x00,拼起来是0x00000000,十进制就是 0(符合预期)。
2. 填充 - 1(memset (arr, -1, sizeof (arr)))
-1 的单字节补码是0xff(计算机中负数用补码存储),所以每个字节填0xff;
int 的 4 个字节都是0xff,拼起来是0xffffffff,这个值的补码解析后就是 - 1(符合预期)。
第四步:代码验证(跑一遍就直观了)
#include <cstdio>
#include <cstring>
int main() {
int arr[3];
// 测试填充0
memset(arr, 0, sizeof(arr));
printf("填充0后:arr[0] = %d\n", arr[0]); // 输出0
// 测试填充-1
memset(arr, -1, sizeof(arr));
printf("填充-1后:arr[0] = %d\n", arr[0]); // 输出-1
// 测试填充1
memset(arr, 1, sizeof(arr));
printf("填充1后:arr[0] = %d\n", arr[0]); // 输出16843009
printf("十六进制:0x%x\n", arr[0]); // 输出0x01010101(验证字节填充结果)
return 0;
}
总结:memset 的使用边界
| 填充值 | 是否适合 memset | 原因 |
|---|---|---|
| 0 | ✅ | 所有字节填 0,任意类型变量解析后都是 0 |
| -1 | ✅ | 所有字节填 0xff,任意类型变量解析后都是 - 1 |
| 1/2/3 等非 0/-1 | ❌ | 逐字节填充后,多字节变量(int/double)解析值≠目标值 |
如果想给 int 数组填充 1、2 这类普通数值,不要用 memset,改用循环或 C++ 的std::fill:
// 正确填充int数组为1的方式
int arr[5];
for (int i = 0; i < 5; ++i) {
arr[i] = 1; // 每个int直接赋值1,而非逐字节填
}
// 或C++的std::fill(更简洁)
#include <algorithm>
std::fill(arr, arr+5, 1);
766

被折叠的 条评论
为什么被折叠?



