目录
C语言中内存函数主要用于对内存空间进行操作,可分为内存拷贝、内存设置、内存比较和动态内
存管理等几类,以下是详细介绍:
1.memcpy函数
1.1函数定义
memcpy 是C语言标准库函数,用于在内存中复制数据块,在 <string.h> 头文件中声明 。以下是
详细介绍:
1.2函数原型
void* memcpy(void* destination, const void* source, size_t num);
- destination :指向用于存储复制内容的目标内存块的指针,类型为 void* ,这意味着它可以接
受任意类型的指针。
- source :指向要复制的数据源内存块的指针,类型为 const void* ,表明该指针指向的内容不
会在函数中被修改。
- num :要复制的字节数,类型为 size_t ,它是一个无符号整数类型,通常用于表示对象的大
小。
1.3函数功能
从 source 所指向的内存地址起始位置开始,将 num 个字节的数据直接复制到 destination 所
指向的内存地址起始位置中 。复制过程是逐字节进行,不关心被复制数据的具体类型,可用于字
符数组、整型数组、结构体、类等任意数据类型。例如:
1.4代码演示:
#include <stdio.h>
#include <string.h>
int main() {
char src[10] = "hello";
char dst[10] = {0};
memcpy(dst, src, strlen(src) + 1); // 复制字符串,包括'\0'
printf("%s\n", dst);
int arr1[3] = {1, 2, 3};
int arr2[3];
memcpy(arr2, arr1, sizeof(arr1)); // 复制整型数组
for (int i = 0; i < 3; i++) {
printf("%d ", arr2[i]);
}
return 0;
}
1.5注意事项
- 内存空间要求:目标内存块 destination 必须提前分配足够大空间,以容纳 num 个字节数据,
否则会导致缓冲区溢出,引发未定义行为 。
- 内存重叠问题:源内存块 source 和目标内存块 destination 所指区域不能重叠。若发生重叠,
复制结果未定义,这种情况下应使用 memmove 函数,它能安全处理重叠内存区域的复制。
- 数据类型无关性:该函数不检查源数据中是否有终止符(如字符串的 '\0' ) ,始终精确复制指
定的 num 个字节。这在复制包含 '\0' 数据(如二进制数据)时很有用,但处理字符串时要注意
手动添加或处理结束符 。
2.memmove函数
2.1函数定义
memmove 是 C 语言标准库函数,用于安全复制内存块,声明于 <string.h> 头文件。以下是详细
说明:
2.2函数原型
void* memmove(void* destination, const void* source, size_t num);
- destination :目标内存块指针( void* ,可接受任意类型)。
- source :源内存块指针( const void* ,不可修改源数据)。
- num :要复制的字节数( size_t 无符号整数)。
2.3函数功能
从 source 指向的内存区域复制 num 个字节到 destination 指向的区域。
与 memcpy 的关键区别:
- 允许内存重叠:即使 source 和 destination 指向的区域有重叠, memmove 也能正确复制数
据。
- 例如:复制数组中某段重叠区域时, memmove 会先将源数据临时缓存,避免覆盖未复制的内
容。
2.4代码演示:
#include <stdio.h>
#include <string.h>
int main() {
// 场景:内存重叠的数组复制(向前覆盖)
int arr[] = {1, 2, 3, 4, 5};
size_t len = sizeof(arr) / sizeof(arr[0]);
// 将前 3 个元素复制到从第 2 个元素开始的位置(重叠区域)
memmove(arr + 1, arr, 3 * sizeof(int)); // 结果:[1, 1, 2, 4, 5]
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]); // 输出:1 1 2 4 5
}
return 0;
}
2.5注意事项
1. 内存分配:目标区域需提前分配足够空间,避免缓冲区溢出。
2. 安全复制:若明确内存无重叠, memcpy 可能更高效(因无需处理缓存逻辑);若可能重叠,
必须用 memmove 。
3. 数据类型无关:和 memcpy 一样,按字节复制,适用于任意数据类型(如结构体、二进制数
据)。
2.6与memcpy的区别
- memmove :安全处理重叠内存的复制,适用于不确定内存是否重叠的场景。
- memcpy :高效处理非重叠内存的复制,但重叠时结果未定义。
3.memset函数
3.1函数定义
memset 是 C 语言标准库函数,用于初始化内存块,声明于 <string.h> 头文件。以下是详细说
明:
3.2函数原型
void* memset(void* s, int c, size_t n);
- s :目标内存块指针( void* ,可接受任意类型)。
- c :要设置的值(会被转换为 unsigned char 类型)。
- n :要初始化的字节数( size_t 无符号整数)。
3.3函数功能
将 s 指向的内存区域的前 n 个字节逐字节设置为 c 的值(实际操作时, c 会被强制转换为
unsigned char 类型)。
适用场景:
- 初始化数组、结构体为特定值(如全零、全 \0 )。
- 清空内存块(如用 0 填充)。
3.4代码演示:
#include <stdio.h>
#include <string.h>
int main() {
// 初始化字符数组为全 'a'
char str[10];
memset(str, 'a', sizeof(str)); // str 内容:"aaaaaaaaaa"
printf("%s\n", str); // 输出:aaaaaaaaaa
// 初始化整型数组为全 0(注意:仅当 0 的二进制字节模式全为 0 时有效)
int arr[5];
memset(arr, 0, sizeof(arr)); // 所有元素被设为 0
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]); // 输出:0 0 0 0 0
}
// 结构体初始化(设为全零)
struct Data { int x; float y; };
struct Data data;
memset(&data, 0, sizeof(data)); // 等价于 data.x=0; data.y=0.0f;
return 0;
}
z3.5注意事项
1. 按字节赋值:
- memset 是逐字节操作,因此对多字节数据类型(如 int 、 float )赋值时需谨慎。
- 例: memset(arr, 1, sizeof(arr)) 会将每个字节设为 1 ,但整型 1 的二进制是 0x00000001 ,
逐字节填充后可能变为 0x01010101 (取决于字节序),结果并非预期的 1 。
- 正确做法:多字节类型需逐个元素初始化,或用 0 填充(因 0 的字节模式全为 0 )。
2. 内存越界:
- 目标指针 s 必须指向有效内存,且 n 不能超过该内存块的大小,否则会引发未定义行为(如程
序崩溃)。
3. 与字符串的区别:
- 处理字符串时, memset 不会自动添加 '\0' 终止符,需手动控制长度(如复制字符串时需包含
'\0' )。
4.memcmp函数
4.1函数定义
memcmp 是 C 语言标准库函数,用于比较两个内存块的二进制数据,声明于 <string.h> 头文
件。以下是详细说明:
4.2函数原型
int memcmp(const void* s1, const void* s2, size_t n);
- s1 / s2 :指向待比较的两个内存块的指针( const void* ,不可修改数据)。
- n :要比较的字节数( size_t 无符号整数)。
4.3函数功能
从 s1 和 s2 指向的内存区域的前 n 个字节开始,按字节顺序逐字节比较二进制值,直到发现不
相等的字节或比较完 n 个字节为止。
返回值
- < 0 : s1 中第一个不相等的字节的值 小于 s2 对应字节的值。
- = 0 :两个内存块的前 n 个字节完全相等。
- > 0 : s1 中第一个不相等的字节的值 大于 s2 对应字节的值。
4.4代码演示:
#include <stdio.h>
#include <string.h>
int main() {
// 比较字符数组(按 ASCII 码值)
char str1[] = "hello";
char str2[] = "helloworld";
int result = memcmp(str1, str2, 5); // 前 5 字节相等,返回 0
printf("memcmp result: %d\n", result); // 输出:0
// 比较整型数组(按二进制字节)
int arr1[] = {0x1234, 0x5678}; // 假设小端序,内存中为 [0x34, 0x12, 0x78, 0x56]
int arr2[] = {0x1234, 0x5670}; // 内存中为 [0x34, 0x12, 0x70, 0x56]
result = memcmp(arr1, arr2, sizeof(int) * 2); // 前 4 字节相等,第 5 字节(0x78 vs 0x70)不相等
printf("memcmp result: %d\n", result); // 输出:正数(因 0x78 > 0x70)
// 比较结构体(按内存布局)
struct Data { char a; int b; } data1 = {'a', 100}, data2 = {'a', 200};
result = memcmp(&data1, &data2, sizeof(struct Data)); // 前 1 字节相等,第 2-5 字节(100 vs 200 的二进制)不同
printf("memcmp result: %d\n", result); // 输出:负数(因 100 < 200 的二进制值)
return 0;
}
4.5注意事项
1. 二进制比较:
- 与 strcmp 不同, memcmp 会严格比较每个字节的二进制值,包括 \0 在内的所有字节
( strcmp 遇到 \0 会提前终止)。
- 例: memcmp("abc", "ab\0c", 3) 返回 0 (前 3 字节均为 'a' 、 'b' 、 '\0' )。
2. 长度控制:
- 若 n 超过实际内存块大小,会访问越界内存,导致未定义行为。
3. 数据类型无关:
- 可用于比较任意类型的数据(如数组、结构体、二进制文件数据),只需确保比较长度 n 正
确。
以上便是与内存处理有关的四个函数,希望大家能够理解,感谢大家的观看!