欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > [C]基础15.C语言内存函数

[C]基础15.C语言内存函数

2025/5/24 18:57:20 来源:https://blog.csdn.net/m0_71486972/article/details/148162706  浏览:    关键词:[C]基础15.C语言内存函数
  • 博客主页:向不悔
  • 本篇专栏:[C]
  • 您的支持,是我的创作动力。

文章目录

  • 0、总结
  • 1、memcpy使用和模拟实现
    • 1.1 memcpy的使用
    • 1.2 memcpy的模拟实现
  • 2、memmove使用和模拟实现
    • 2.1 memmove的使用
    • 2.2 memmove的模拟实现
  • 3、memset函数的使用
    • 3.1 memset的使用
    • 3.2 memset的模拟实现
  • 4、memcmp函数的使用
    • 4.1 memcmp的使用
    • 4.2 memcmp的模拟实现


0、总结

在这里插入图片描述

在C语言中,有一些常用的内存操作函数,它们在处理内存数据时非常实用。下面将详细介绍memcpymemmovememsetmemcmp这四个函数的使用方法及模拟实现。

1、memcpy使用和模拟实现

1.1 memcpy的使用

介绍:

  • 头文件:string.h
  • 函数原型:void* memcpy(void* destination, const void* source, size_t num);
  • 作用:从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
  • 参考:https://legacy.cplusplus.com/reference/cstring/memcpy/

总结如下:

  • 源和目标内存块不能重叠,否则会导致未定义行为。
  • 不检查源数据中的终止符,总是复制指定的字节数。
  • 目标内存空间需要足够大以容纳复制的数据,否则会导致内存溢出。

1.2 memcpy的模拟实现

#include <stdio.h>
#include <assert.h> // 用于 assertvoid* my_memcpy(void* dst, const void* src, size_t count) {// 保存目标地址,方便最后返回void* ret = dst;// 断言确保目标和源地址都非空,防止出现空指针异常assert(dst != NULL && src != NULL);while (count--) {// 将源地址对应的字节内容复制到目标地址对应的字节位置*(char*)dst = *(char*)src;// 目标和源地址分别向后移动一位,指向下一个字节位置dst = (char*)dst + 1;src = (char*)src + 1;}return ret;
}// 主函数
int main() {int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };my_memcpy(arr2, arr1, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr2[i]);}return 0;
}

思考1:为什么((char*)src)++不行?

  • ((char*)src)++是错误的,因为它试图对一个临时值进行递增操作,导致未定义行为。
  • src = (char*)src + 1;是正确的,因为它先进行类型转换,再进行加法操作,最后将结果赋值给 src,符合C语言的语法规则和逻辑。

思考2 :memcpystrncpy的区别?

  • 操作对象 :memcpy操作的是内存块,按字节复制;strncpy专门用于处理字符串,复制字符直到遇到字符串结束符'\0'或复制完指定数量的字符。
  • 终止条件 :memcpy不检查字符串结束符'\0',严格复制指定字节数;strncpy会在遇到'\0'时停止复制(除非要复制的字符数大于字符串长度)。
  • 安全性 :strncpy在处理字符串时更安全,能避免因未正确处理结束符导致的缓冲区溢出等问题;memcpy若使用不当,容易引发内存越界问题。

2、memmove使用和模拟实现

2.1 memmove的使用

介绍:

  • 头文件:string.h
  • 函数原型:void* memmove(void* destination, const void* source, size_t num);
  • 作用:功能和memcpy一样,差别是memmove能处理源空间和目标空间的重叠情况。
  • 参考:https://legacy.cplusplus.com/reference/cstring/memmove/

2.2 memmove的模拟实现

讲解模拟实现之前,先讲讲while(num--),这个理解很重要。

#include <stdio.h>// 主函数
int main() {int num = 3;while (num--) {printf("num is now: %d\n", num);}return 0;
}
运行:
num is now: 2
num is now: 1
num is now: 0

总结:

  • 当前值用于判断循环条件,然后才减 1。

然后讲解模拟实现:

#include <stdio.h>
#include <assert.h> void* my_memmove(void* dst, const void* src, size_t count) {assert(dst != NULL && src != NULL);void* ret = dst;if (dst < src){while (count--){*(char*)dst = *(char*)src;dst = (char*)dst + 1;src = (char*)src + 1;}}else{while (count--){*((char*)dst + count) = *((char*)src + count);}}return ret;
}// 主函数
int main() {int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };//my_memmove(arr1, arr1+2, 20);  // d < smy_memmove(arr1 + 4, arr1 + 2, 20);  // d < sint i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}printf("hello");return 0;
}

总结:在移动过程中,想象目标地址(dst)可以灵活调整位置。在不断比较中清晰掌握目标地址小于源地址(dst < src)和源地址大于目标地址(src > dst)的两种情况。

3、memset函数的使用

3.1 memset的使用

介绍:

  • 头文件:string.h
  • 函数原型:void* memset(void* ptr, int value, size_t num);
  • 作用:将ptr指向的内存块的前num个字节都设置为value(以unsigned char形式解释)。
  • 参考:https://legacy.cplusplus.com/reference/cstring/memset/

3.2 memset的模拟实现

#include <stdio.h>void* my_memset(void* ptr, int value, size_t num) {unsigned char* p = (unsigned char*)ptr;while (num--) {*p++ = (unsigned char)value;}return ptr;
}// 主函数
int main() {char str[] = "almost every programmer should know memset!";my_memset(str, '-', 6);printf("%s\n", str);return 0;
}
运行:
------ every programmer should know memset!

4、memcmp函数的使用

4.1 memcmp的使用

介绍:

  • 头文件:string.h
  • 函数原型:int memcmp(const void* ptr1, const void* ptr2, size_t num);
  • 作用:比较ptr1ptr2指向的内存块的前num个字节。若相等返回0;若ptr1所指内存大于ptr2,返回正数;否则返回负数。
  • 参考:https://legacy.cplusplus.com/reference/cstring/memcmp/

4.2 memcmp的模拟实现

#include <stdio.h>int my_memcmp(const void* ptr1, const void* ptr2, size_t num) {const unsigned char* p1 = (const unsigned char*)ptr1;const unsigned char* p2 = (const unsigned char*)ptr2;while (num--) {if (*p1 != *p2) {return *p1 - *p2;}p1++;p2++;}return 0;
}// 主函数
int main() {char buffer1[] = "DWgaOtP12df0";char buffer2[] = "DWGAOTP12DF0";int n = my_memcmp(buffer1, buffer2, sizeof(buffer1));if (n > 0) {printf("'%s' is greater than '%s'.\n", buffer1, buffer2);} else if (n < 0) {printf("'%s' is less than '%s'.\n", buffer1, buffer2);} else {printf("'%s' is the same as '%s'.\n", buffer1, buffer2);}return 0;
}
运行:
'DWgaOtP12df0' is greater than 'DWGAOTP12DF0'.

完。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词