内存函数:通常指的是在编程中用于处理内存操作的函数,这些函数可以用来分配、释放、复制、比较等内存相关的操作。在C语言中,这些内存函数 memcpy()
、memmove()
、memset()
、memcmp()
都需要引用头文件
。
memcpy()
函数的原型如下:
void *memcpy(void *dest, const void *src, size_t n);
dest
:目标内存地址,即要将数据复制到的位置。src
:源内存地址,即要复制数据的起始位置。n
:要复制的字节数。memcpy()
函数会从源内存地址 src
复制 n
个字节的数据到目标内存地址 dest
,并返回目标内存地址 dest
。
#include
void *memcpy_custom(void *dest, const void *src, size_t n) {
// 将源地址src的内容复制到目标地址dest
// 注意:此处假设目标地址和源地址不会重叠
// 将void指针转换为char指针,方便按字节进行操作
char *p_dest = (char *)dest;
const char *p_src = (const char *)src;
// 逐字节复制数据
for (size_t i = 0; i < n; i++) {
p_dest[i] = p_src[i];
}
return dest;
}
int main() {
char src[] = "Hello, world!";
char dest[20];
// 调用自定义的memcpy函数
memcpy_custom(dest, src, sizeof(src));
// 输出复制后的字符串
printf("Copied string: %s\n", dest);
return 0;
}
假设存在两片这样的空间由两个指针“dest”和“src”维护,解引用赋值过去相当于copy过去一个字节
然后“dest++”和“src++”就指向下一内存单元,重复之前的操作直至来到最后一个内存单元,也就是第n个,至此操作完成返回目标内存的起始地址
memmove()
类似于 memcpy()
,但更安全,可以处理内存块重叠的情况,内存块重叠情况就是当我们
src所指向的内存块和dest所指向的内存块发生重叠的情况,如下图
当我们如果想进行像memcpy() 那样操作时就会篡改src所指向的内存块从而达不到copy效果当我们走到最后变成这样
而memmove就是避免这种情况而造就的,实现原理也很简单当src的起始位置大于dest的起始位置,我们就从后往前复制,当src的起始位置小于dest的起始位置,就从前向后复制,至此实现正确复制,这样做的原理就是先把重合部分拿出来复制,这样就可以避免篡改源内存块
memmove实现
#include
void *memmove_custom(void *dest, const void *src, size_t n) {
// 将源地址src的内容复制到目标地址dest
// 处理重叠情况时,从后往前复制
// 将void指针转换为char指针,方便按字节进行操作
char *p_dest = (char *)dest;
const char *p_src = (const char *)src;
// 处理重叠情况时,从后往前复制
if (p_dest > p_src && p_dest < p_src + n) {
for (size_t i = n - 1; i < n; i--) {
p_dest[i] = p_src[i];
}
} else {
// 普通情况下,从前往后复制
for (size_t i = 0; i < n; i++) {
p_dest[i] = p_src[i];
}
}
return dest;
}
int main() {
char src[] = "Hello, world!";
char dest[20];
// 调用自定义的memmove函数
memmove_custom(dest, src, sizeof(src));
// 输出复制后的字符串
printf("Copied string: %s\n", dest);
return 0;
}
memcmp()
是C语言中用于比较内存区域的函数,类似于strncmp函数但是memcmp更加通用,因为它比较的是内存中的值而不只限于字符串
其原型如下:
int memcmp(const void *s1, const void *s2, size_t n);
s1
:指向要比较的第一个内存区域的指针。s2
:指向要比较的第二个内存区域的指针。n
:要比较的字节数。memcmp()
函数会比较 s1
和 s2
所指向的内存区域的前 n
个字节,并返回一个整数来表示比较结果。
实现:
#include
int memcmp_custom(const void *s1, const void *s2, size_t n) {
// 将void指针转换为char指针,方便按字节进行比较
const unsigned char *p1 = (const unsigned char *)s1;
const unsigned char *p2 = (const unsigned char *)s2;
// 逐字节比较数据
for (size_t i = 0; i < n; i++) {
if (p1[i] != p2[i]) {
// 如果有不相等的字节,则返回它们的差值
return (p1[i] > p2[i]) ? 1 : -1;
}
}
// 如果所有字节都相等,则返回0
return 0;
}
int main() {
char s1[] = "Hello";
char s2[] = "Hella";
// 调用自定义的memcmp函数
int result = memcmp_custom(s1, s2, 5);
if (result == 0) {
printf("s1 和 s2 相等\n");
} else if (result > 0) {
printf("s1 大于 s2\n");
} else {
printf("s1 小于 s2\n");
}
return 0;
}
memset()
是C语言中用于设置内存块的函数,其原型如下
void *memset(void *s, int c, size_t n);
s
:指向要设置的内存块的指针。c
:要设置的值,以整数形式给出,通常是一个字节的值。n
:要设置的字节数。memset()
函数将指定的值 c
复制到 s
所指向的内存块的前 n
个字节中。通常情况下,c
是一个无符号字符或整数(0~255),会被转换成无符号字符并复制到内存块中。
memset()
主要用于初始化内存块,可以用来快速将一段内存区域填充为指定的值。它经常用于数组初始化、清除内存等操作。
实现:
#include
void *memset_custom(void *s, int c, size_t n) {
// 将指定的值c复制到s所指向的内存块的前n个字节中
// 将void指针转换为char指针,方便按字节进行操作
unsigned char *p = (unsigned char *)s;
// 将指定的值复制到内存块中
for (size_t i = 0; i < n; i++) {
p[i] = (unsigned char)c;
}
return s;
}
int main() {
char arr[10];
// 调用自定义的memset函数,将数组arr的前5个字节设置为'a'的ASCII码值
memset_custom(arr, 'a', 5);
// 输出设置后的数组内容
for (int i = 0; i < 10; i++) {
printf("%c ", arr[i]);
}
printf("\n");
return 0;
}