当前位置: 首页 > news >正文

C/C++---memset()初始化

memset 是 C/C++ 标准库中用于内存块初始化的函数,定义在 <cstring> 头文件中。它的核心功能是将一块连续内存的每个字节都设置为指定的值,常用于初始化数组、结构体等数据结构。

一、函数原型

void* memset(void* ptr, int value, size_t num);
  • 参数说明
    • ptr:指向要初始化的内存块的起始地址(必须是可修改的内存,如数组、动态分配的内存等)。
    • value:要设置的值(虽然类型是 int,但实际只会使用其低 8 位,即 unsigned char 范围内的值)。
    • num:要设置的字节数(size_t 类型,通常是内存块的总大小)。
  • 返回值:返回指向内存块起始地址的指针(即 ptr)。

二、工作原理

memset 会从 ptr 指向的地址开始,逐个字节地将内存设置为 value 的低 8 位。例如:

int arr[5];
memset(arr, 0, sizeof(arr));  // 将arr的每个字节都设为0
  • sizeof(arr) 计算数组总字节数(5 * 4 = 20 字节,假设 int 为 4 字节)。
  • memset 会将这 20 个字节全部设置为 0x00,最终数组每个元素都为 0

三、使用场景

  1. 初始化数组为 0 或 -1
    最常见的用法是将数组初始化为全 0 或全 -1(因二进制特性,见下文注意事项):

    int a[100];
    memset(a, 0, 100 * sizeof(int));  // 全0初始化char str[20];
    memset(str, '\0', 20);  // 字符串结束符初始化(等价于0)
    
  2. 清空结构体/缓冲区
    用于重置结构体或内存缓冲区的内容:

    struct Student {int id;char name[20];
    };
    Student s;
    memset(&s, 0, sizeof(Student));  // 结构体成员全设为0
    
  3. 快速填充字符数组
    对字符数组(每个元素占 1 字节)可直接填充指定字符:

    char buf[10];
    memset(buf, 'a', 10);  // 数组元素全为 'a'(ASCII码97)
    

四、关键注意事项

  1. 按字节赋值的局限性
    memset逐字节设置的,因此仅适用于以下情况:

    • 目标类型为单字节类型(如 charunsigned char)。
    • 希望将多字节类型(如 intlong)的每个字节都设为相同值(如 0 或 -1)。

    ❌ 错误示例(对 int 数组填充非 0/-1 的值):

    int arr[3];
    memset(arr, 1, 3 * sizeof(int));  // 错误!结果不是 [1,1,1]
    

    原因:int 占 4 字节,memset 会将每个字节设为 0x01,实际每个元素为 0x01010101(十进制 16843009),而非 1。

  2. value 参数的有效范围
    虽然 value 类型是 int,但实际只使用低 8 位(0~255-128~127)。例如:

    memset(ptr, 256, num);  // 等价于 memset(ptr, 0, num)(256的低8位为0)
    memset(ptr, -1, num);   // 等价于填充 0xFF(因-1的二进制补码为全1)
    
  3. 避免越界访问
    num 参数必须小于等于 ptr 指向的内存块大小,否则会导致缓冲区溢出,引发未定义行为(如程序崩溃、数据损坏)。

  4. std::fill 的区别
    C++ 中的 std::fill 是更通用的初始化工具,按元素赋值而非按字节,适用于任何类型:

    #include <algorithm>  // 需包含此头文件
    int arr[3];
    std::fill(arr, arr + 3, 1);  // 正确将每个元素设为1(按int类型赋值)
    
    • memset 速度更快(底层优化),但适用场景有限。
    • std::fill 更灵活,支持任意值初始化,但性能略低。

五、常见错误用法

  1. 对非字节类型填充任意值(如上述 int 数组填充 1)。
  2. 错误计算 num 大小(如用元素个数代替字节数):
    int arr[10];
    memset(arr, 0, 10);  // 错误!仅初始化前10字节(不足3个int元素)
    
  3. 对只读内存(如字符串常量)使用 memset
    char* str = "hello";
    memset(str, 'a', 5);  // 错误!字符串常量不可修改,会导致崩溃
    

memset 是高效的内存初始化工具,核心作用是按字节批量设置内存值,但需注意:

  • 仅适用于单字节类型或多字节类型的全 0/-1 初始化。
  • 严格控制 num 参数,避免越界。
  • 复杂类型的初始化优先考虑 std::fill 等更安全的方法。
http://www.dtcms.com/a/352300.html

相关文章:

  • 31.Encoder-Decoder(Seq2Seq)
  • MySQL8 排名窗口函数实战
  • 面试:Spring
  • 30.LSTM-长短时记忆单元
  • 抢红包案例加强版
  • 并行多核体系结构基础——共享存储并行编程(笔记)
  • 网络编程close学习
  • Java大厂面试实录:从Spring Boot到Kubernetes的全链路技术突围
  • python命名规则(PEP 8 速查表),以及自定义属性
  • 深度感知卷积和深度感知平均池化
  • python自动测试 crictl 可以从哪些国内镜像源成功拉取镜像
  • pulsar、rocketmq常用命令
  • C#由Dictionary不正确释放造成的内存泄漏问题与GC代系
  • Text to Speech技术详解与实战:GPT-4o Mini TTS API应用指南
  • 从“脚本语言”到“企业级引擎”——PHP 在 2025 年技术栈中的再定位
  • Linux服务器安全配置与NTP时间同步
  • 记录一下,qt问题:qt ui文件的改动无法更新到cpp
  • 疯狂星期四文案网第51天运营日记
  • Typescript入门-interface讲解
  • 类型签名,位置参数,关键字参数
  • open webui源码分析8—管道
  • 域名常见问题集(十一)——为什么要进行域名管理?
  • 【实时Linux实战系列】基于实时Linux的音频实时监控系统
  • 从16个粉丝到680万年收入:AI创业的117天奇迹
  • 声明式微服务通信新范式:OpenFeign如何简化RestTemplate调用
  • Windows下实现类似`watch nvidia-smi`的实时监控效果
  • 进入docker中mysql容器的方法
  • Java:TreeSet的使用
  • (Arxiv-2024)VideoMaker:零样本定制化视频生成,依托于视频扩散模型的内在力量
  • QT qml(quick3D)模型的移动