C语言程序的内存处理函数:深入理解与实践
·
文章目录
1.内存处理函数的用处
2.内存处理函数的模型和应用场景
- memcpy
在 C 语言中,memcpy 是核心内存操作函数,用于从源地址向目标地址拷贝指定字节数的内存数据,且不做数据类型解析(按字节逐位拷贝),是高效且通用的内存复制工具,定义在 <string.h> 头文件中。
形式(参数含义)
void *memcpy(void *dest, const void *src, size_t n);
| 参数 | 含义 |
|---|---|
| dest | 目标内存地址(拷贝后数据存放的位置),需保证该区域有足够空间容纳 n 字节 |
| src | 源内存地址(待拷贝数据的起始位置),const 表示源数据只读,防止被修改 |
| n | 要拷贝的字节数,size_t 是无符号整型 |
- 使用样例:1.拷贝基本类型数组
#include <stdio.h>
#include <string.h>
int main() {
int src[] = {1, 2, 3, 4, 5};
int dest[5];
// 拷贝整个int数组:5个int元素 × 4字节/int = 20字节
memcpy(dest, src, sizeof(src));
for (int i = 0; i < 5; i++) {
printf("%d ", dest[i]); // 输出:1 2 3 4 5
}
return 0;
}
2.拷贝部分数据(指定字节数)
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, memcpy!";
char dest[20] = {0};
// 仅拷贝前5个字节
memcpy(dest, src, 5);
printf("dest: %s\n", dest); // 输出:dest: Hello
return 0;
}
- 在使用memcpy函数的时候我们要注意:
- 给定的参数要对应,类型一致。
- 注意内存重叠问题当我们的dest和src的位置处于重叠状态,memcpy是不可以处理的。
- 返回值为 dest 指针,可直接用于后续操作。
- 必须保证 dest 有至少 n 字节的可用空间,否则会导致内存越界。
- memmove
在 C 语言中,memmove 是专门解决内存重叠场景的内存拷贝函数,与 memcpy 核心功能一致(字节级拷贝),但能安全处理源地址(src)和目标地址(dest)内存区域重叠的情况,定义在 <string.h> 头文件中。
使用(参数含义)
void *memmove(void *dest, const void *src, size_t n);
| 参数 | 含义 |
|---|---|
| dest | 目标内存地址,需保证有至少 n 字节可用空间 |
| src | 源内存地址(待拷贝数据的起始位置),const 表示源数据只读,防止被修改 |
| n | 要拷贝的字节数,size_t 是无符号整型 |
- 使用样例:1.处理内存重叠
#include <stdio.h>
#include <string.h>
int main() {
char arr[] = "1234567890";
// 场景:dest = src + 2(内存重叠)
// 用 memcpy 会出错,用 memmove 正确
memmove(arr + 2, arr, 5);
printf("arr: %s\n", arr); // 输出:arr: 1212345890
return 0;
}
- 使用样例:2.普通场景(无重叠,等价于 memcpy)
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[10];
} Student;
int main() {
Student s1 = {101, "LiSi"};
Student s2;
// 无重叠,memmove 等价于 memcpy
memmove(&s2, &s1, sizeof(Student));
printf("id: %d, name: %s\n", s2.id, s2.name); // 输出:id: 101, name: LiSi
return 0;
}
- 在使用memmove函数的时候我们要注意:
- 必须保证 dest 有至少 n 字节的可用空间,否则会内存越界。
- memmove 是标准库函数,所有 C 编译器均支持,可放心替代 memcpy 用于所有拷贝场景。
- 处理我们的重叠问题专用。
- 返回值为: dest 指针
- memset
在 C 语言中,memset 是用于按字节批量初始化内存的核心函数,能快速将指定内存区域的每一个字节设置为相同的数值,定义在 <string.h> 头文件中。它是初始化内存(如清零、填充固定值)的高频工具,效率远高于手动循环赋值。
形式(参数含义)
void *memset(void *s, int c, size_t n);
| 参数 | 含义 |
|---|---|
| s | 待初始化的内存起始地址(如数组、结构体指针) |
| c | 要设置的字节值(实际只取低 8 位,范围 0~255,超出会截断) |
| n | 要初始化的字节数,无符号整型 |
- 使用样例:1.内存清零
#include <stdio.h>
#include <string.h>
int main() {
// 1. 初始化字符数组
char str[20];
memset(str, 0, sizeof(str)); // 全部字节置0
strcpy(str, "memset test");
printf("str: %s\n", str); // 输出:str: memset test
// 2. 初始化整型数组
int arr[5] = {1, 2, 3, 4, 5};
memset(arr, 0, sizeof(arr)); // 每个字节置0 → 整个int数组为0
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]); // 输出:0 0 0 0 0
}
return 0;
}
- 使用样例:2.初始化结构体
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[20];
float score;
} Student;
int main() {
Student s = {101, "ZhangSan", 95.5};
memset(&s, 0, sizeof(Student)); // 结构体所有字节置0
printf("id: %d, name: %s, score: %.1f\n", s.id, s.name, s.score);
// 输出:id: 0, name: , score: 0.0
return 0;
}
- 在使用memset函数的时候我们要注意:
- 按字节赋值仅对单字节类型(char)能直接设置任意值(如 ‘a’、10),对多字节类型(int、float、long),仅能安全设置 0(所有字节为 0 时,数值就是 0);
- 必须保证 n 不超过 s 指向的内存可用范围,否则会内存越界。
- 返回值为: s 指针
- memcmp
在 C 语言中,memcmp 是用于按字节逐位比较两块内存区域的核心函数,可比较任意类型的内存数据(字符、整型、结构体等),返回值反映两块内存的****大小关系,定义在 <string.h> 头文件中。
形式(参数含义)
int memcmp(const void *s1, const void *s2, size_t n);
| 参数 | 含义 |
|---|---|
| s1 | 第一块待比较的内存起始地址(只读,不修改) |
| s2 | 第二块待比较的内存起始地址(只读,不修改) |
| n | 要比较的字节数,无符号整型 |
- 返回值–返回值为 int,反映 s1 和 s2 前 n 字节的比较结果:
| 返回值 | 含义 |
|---|---|
| < 0 | s1 中第一个不同字节的二进制值 < s2 对应字节 |
| = 0 | s1 和 s2 前 n 字节完全相同 |
| > 0 | s1 中第一个不同字节的二进制值 > s2 对应字节 |
关键:比较仅在第一个不同字节处终止,后续字节不再对比;若前 n 字节均相同,返回 0。
- 使用样例:1.比较字符数组
#include <stdio.h>
#include <string.h>
int main() {
char s1[] = "Hello";
char s2[] = "World";
char s3[] = "Hello";
// 比较前5个字节
int res1 = memcmp(s1, s2, 5);
int res2 = memcmp(s1, s3, 5);
printf("s1 vs s2: %d\n", res1); // 输出:-1('H'(0x48) < 'W'(0x57))
printf("s1 vs s3: %d\n", res2); // 输出:0(完全相同)
return 0;
}
- 使用样例:2.比较整型数组
#include <stdio.h>
#include <string.h>
int main() {
int arr1[] = {1, 2, 3, 4};
int arr2[] = {1, 2, 4, 5};
int arr3[] = {1, 2, 3, 4};
// 比较前3个int元素(3×4=12字节)
int res = memcmp(arr1, arr2, 12);
printf("arr1 vs arr2: %d\n", res); // 输出:-1(第三个元素3(0x03) < 4(0x04))
res = memcmp(arr1, arr3, sizeof(arr1));
printf("arr1 vs arr3: %d\n", res); // 输出:0(完全相同)
return 0;
}
- 在使用memcmp函数的时候我们要注意:
- 按字节比较的规则:
–‘a’(0x61) > ‘A’(0x41);
–数值 1< 数值 255;
--负数的补码形式会按二进制值对比(如 int -1 的补码是 0xFFFFFFFF,比 int 1 大)。 - memcmp 不识别 \0,仅按指定 n 字节比较;而 strcmp 会遇 \0 终止,且仅比较字符串。
- 返回值是int类型的我们要记好不要区分不开
3.比较内存函数的区别
memcpy vs memmove vs memset vs memcmp(核心区别)
| 特性 | memcpy | memmove | memset | memcmp |
|---|---|---|---|---|
| 核心功能 | 字节级内存拷贝 | 字节级内存拷贝(安全处理重叠) | 字节级内存初始化(置固定值) | 字节级内存比较 |
| 关键参数 | dest, src, n(字节数) | dest, src, n(字节数) | s, c(字节值), n(字节数) | s1, s2, n(字节数) |
| 内存重叠 | 不处理(结果未定义) | 安全处理(正向 / 反向拷贝) | 无重叠概念 | 无重叠概念 |
| 返回值 | 指向 dest 的指针 | 指向 dest 的指针 | 指向 s 的指针 | int(<0/0/>0) |
| 性能 | 最高(无额外判断) | 略低(多地址判断) | 极高(批量字节赋值) | 逐字节对比(找到差异即终止) |
| 核心限制 | 仅无重叠场景可用 | 无明显限制 | 仅单字节类型可任意置值 | 结构体填充字节可能导致误判 |
总结😗
- memcpy:无重叠的高效内存拷贝
核心场景:明确 目标内存无重叠时,快速拷贝任意类型数据。 - memmove:任意场景的安全内存拷贝
核心场景:目标内存可能重叠,或不确定是否重叠时的拷贝。 - memset:批量内存初始化(尤其清零)
核心场景:快速初始化内存,优先用于 “清零”,其次是单字节类型填充。 - memcmp:字节级内存对比
核心场景:对比任意类型内存的二进制内容,判断是否一致或大小关系
更多推荐


所有评论(0)