如何用基础C++实现memset?基于指针与地址运算符的技术问询
用基础C++实现memset:从原理到实用代码
嘿,我来帮你把memset的实现逻辑掰扯清楚,不管是给业务线同事讲还是自己理解都够用~首先得明确memset的核心工作原理:它就是把一块连续内存区域的每一个字节都设置成你指定的8位值(uint8_t val),不管这块内存原本存的是int、char还是结构体,都是按字节粒度操作的。
先聊聊你的现有实现
你的递归思路方向是对的,但有两个小问题需要调整:
- 递归的局限性:如果要处理的内存很大(比如几MB),递归调用会耗尽栈空间导致崩溃,业务场景里大内存操作很常见,所以迭代版才是实用选择;
- 多余的异或操作:
*new_or ^= (*new_or & 0xff)其实没必要,我们本来就要覆盖原字节的值,直接*new_or = val就够了,逻辑更清晰,也避免了不必要的计算。
最直观的基础实现(适合业务开发者理解)
用指针+迭代的方式,逻辑一目了然,新手也能看懂:
void my_memset(void* origin, uint8_t val, size_t size) { // 边界处理:如果要设置的字节数为0,直接返回 if (size == 0) { return; } // 把void*转成uint8_t*:因为void*不能直接解引用/移动指针,而uint8_t是1字节类型, // 指针每移动一次正好对应一个内存字节,完美匹配memset的字节级操作要求 uint8_t* byte_ptr = static_cast<uint8_t*>(origin); // 逐个字节赋值:遍历size次,每次给当前指针指向的字节赋值,然后指针下移 for (size_t i = 0; i < size; ++i) { *byte_ptr = val; ++byte_ptr; // 前置递增比后置稍高效,业务场景里差别可以忽略,怎么写都行 } }
这个实现的关键逻辑拆解
- 类型转换:
void*是通用指针,但不能直接操作,转成uint8_t*后,我们能精准控制每次指针移动1个字节,确保每个内存单元都被正确覆盖; - 循环遍历:从内存块的第一个字节开始,依次给每个字节赋值,直到处理完所有
size个字节; - 边界处理:先判断
size == 0的情况,避免无效操作,这是工业级代码的严谨性体现。
进阶优化版(接近工业级memset的思路)
如果要追求更高的效率(比如性能敏感的场景),可以利用内存对齐和批量赋值来减少循环次数,现代CPU访问对齐的内存会更快:
void optimized_memset(void* origin, uint8_t val, size_t size) { uint8_t* byte_ptr = static_cast<uint8_t*>(origin); // 第一步:处理开头不对齐的字节,把指针调整到4字节对齐的位置(适配32位系统,64位可以改成8字节) while (size > 0 && reinterpret_cast<uintptr_t>(byte_ptr) % sizeof(uint32_t) != 0) { *byte_ptr = val; ++byte_ptr; --size; } // 把单字节的val扩展成4字节的重复值:比如val是0xAB,扩展后就是0xABABABAB uint32_t word_val = static_cast<uint32_t>(val); word_val |= word_val << 8; word_val |= word_val << 16; // 第二步:按4字节为单位批量赋值,减少循环次数 uint32_t* word_ptr = reinterpret_cast<uint32_t*>(byte_ptr); while (size >= sizeof(uint32_t)) { *word_ptr = word_val; ++word_ptr; size -= sizeof(uint32_t); } // 第三步:处理剩下的不足4字节的部分 byte_ptr = reinterpret_cast<uint8_t*>(word_ptr); while (size > 0) { *byte_ptr = val; ++byte_ptr; --size; } }
优化思路解释
- 内存对齐:先处理开头几个不对齐的字节,让指针落在CPU更易访问的对齐地址上;
- 批量赋值:把单字节值扩展成多字节的重复值,每次赋值就能覆盖4个字节,循环次数直接减少到原来的1/4;
- 收尾处理:最后把剩下的不足4字节的部分用基础的字节赋值处理,确保所有内存都被覆盖。
总结
- 业务开发场景下,基础迭代版完全够用,逻辑清晰,不容易出错;
- 如果要深入理解工业级实现,进阶优化版能帮你明白memset为什么高效;
- 递归版尽量避免,因为大内存场景下栈溢出风险很高。
内容的提问来源于stack exchange,提问作者Danilo
相关产品推荐
相关产品推荐

