C语言 - 详解 memset 和 memcpy 的使用与区别
【C语言基础】详解 memset 和 memcpy 的使用与区别
在 C 语言开发过程中,操作内存是非常常见的需求。标准库中提供了两个高效处理内存的函数:memset
和 memcpy
。这两个函数虽然名称相似,但功能和应用场景完全不同。本文将对这两个函数的用法、参数含义、使用示例和常见误区进行系统性说明。
一、memset:用于初始化内存
函数原型
void *memset(void *s, int c, size_t n);
参数说明
s
:指向要被设置的内存起始地址;c
:设置的值,只使用该值的低 8 位;n
:要设置的字节数。
基本用途
memset
通常用于将数组或结构体的内存设置为固定值,常见的是设置为 0。
示例 1:将数组清零
int arr[10];memset(arr, 0, sizeof(arr));
这段代码会将 arr
中的所有字节设置为 0,相当于把每个元素都初始化为 0。
示例 2:将缓存区填充为特定字符
char buffer[16];memset(buffer, \'A\', sizeof(buffer));
将 buffer
中的所有字节设置为字符 \'A\'
,即十六进制值 0x41。
二、memcpy:用于内存拷贝
函数原型
void *memcpy(void *dest, const void *src, size_t n);
参数说明
dest
:目标内存地址;src
:源内存地址;n
:要复制的字节数。
基本用途
memcpy
用于将一段内存中的内容复制到另一段内存,适用于复制数组、结构体或任意内存块。
例 1:复制数组内容
int a[5] = {1, 2, 3, 4, 5};int b[5];memcpy(b, a, sizeof(a));
将数组 a
的内容复制到数组 b
中。
例 2:复制字符串内容
char src[] = \"hello\";char dest[10];memcpy(dest, src, strlen(src) + 1); // 包括结尾的 \'\\0\'
将字符串 src
包含末尾的结束符完整复制到 dest
中。
三、功能对比
四、注意
1. memset 设置非零整数数组时的错误用法
int arr[4];memset(arr, 1, sizeof(arr)); // 错误
该代码并不会将每个元素设置为整数 1,而是将每个字节设置为 0x01,结果可能是每个整数变成 0x01010101,即 16843009。这种写法容易造成逻辑错误。
建议:
如需将整数数组每个元素设置为 1,应使用循环赋值:
for (int i = 0; i < 4; i++) { arr[i] = 1;}
2. memcpy 不会自动添加字符串结束符
在复制字符串时,若不手动包含 \'\\0\'
,目标内存可能不是合法字符串。
char src[] = \"abc\";char dst[10];memcpy(dst, src, 3); // 未复制 \'\\0\',dst 不是完整字符串
应写为:
memcpy(dst, src, strlen(src) + 1);
五、应用场景
1. 结构体初始化
struct Config { int id; char name[32]; float value;};struct Config cfg;memset(&cfg, 0, sizeof(cfg));
此操作将结构体所有字段初始化为 0,避免出现未定义值。
2. 缓存区清空
char rx_buffer[64];memset(rx_buffer, 0, sizeof(rx_buffer));
用于网络、串口、文件读取前,清空接收缓存区,防止数据残留。
3. 拷贝数据结构
struct Data a = {1, \"sensor\", 3.14};struct Data b;memcpy(&b, &a, sizeof(struct Data));
快速复制结构体的所有内容,适用于数据缓存、消息转发等场景。
六、总结
memset
和 memcpy
是 C 语言中最基本、最常用的两个内存操作函数:
memset
用于将一段内存设置为统一的字节值,适合初始化或清空。memcpy
用于将一段内存的内容复制到另一段地址,适合数据备份或传输。
正确理解参数含义和工作原理,能够避免常见错误并提升代码的健壮性和效率。在实际开发中,这两个函数经常配合使用,是处理底层数据结构时的重要工具。
如需配合调试观察效果,可通过 GDB 或在代码中加入打印函数,查看内存填充或拷贝前后的变化,以加深理解。
(完)