memset字节级填充

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;,它的内存布局是:

字节位置(假设)0x1000x1010x1020x103
存储内容
2. memset 的工作规则:只认 “字节”,不认 “变量类型”

memset(ptr, c, n) 的逻辑是:

  • ptr指向的内存地址开始;
  • 每一个字节都设置为cc会被转成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,内存布局变成:

字节位置0x1000x1010x1020x103
填充值0x010x010x010x01
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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值