【C语言基础】:内存操作函数

03-27 2306阅读 0评论

文章目录

      • 一、memcpy函数的使用和模拟实现
        • 1.1 memcpy函数的使用
        • 1.2 memcpy函数的模拟实现
        • 二、memmove函数的使用和模拟实现
          • 2.1 memmove函数的使用
          • 2.2 memmove函数的模拟实现
          • 三、memset函数的使用
            • 3.1 menset函数的使用
            • 四、memcmp函数的使用
              • 4.1 memcmp函数的使用

                【C语言基础】:内存操作函数 第1张

                         书山有路勤为径,学海无涯苦作舟。

                创作不易,宝子们!如果这篇文章对你们有帮助的话,别忘了给个免费的赞哟~

                一、memcpy函数的使用和模拟实现

                函数原型:

                void * memcpy ( void * destination, const void * source, size_t num );
                

                内存复制块

                1. 将num字节的值从源指向的位置直接复制到目标指向的内存块。
                2. 源指针和目标指针所指向的对象的底层类型与此函数无关;结果是数据的二进制副本。
                3. 该函数不检查源中是否有任何终止null字符——它总是精确地复制num个字节。
                4. 为了避免溢出,目标参数和源参数所指向的数组的大小应该至少为num字节,并且不应该重叠(对于重叠的内存块,memmove是一种更安全的方法)。
                1.1 memcpy函数的使用

                【示例】:将arr1中的前5个元素拷贝到arr2中

                #include
                #include
                int main()
                {
                	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
                	int arr2[20] = { 0 };
                	memcpy(arr2, arr1, 20);
                	for (int i = 0; i  
                

                【C语言基础】:内存操作函数 第2张

                1.2 memcpy函数的模拟实现

                模拟思路:

                函数参数和返回类型:mencpy不仅可以将拷贝整形数据,其他的数据类型也可以拷贝,即参数类型根据传入的数据类型决定,需要接受任意类型的地址,所以参数类型可以定义成void*,因为src是原数据,我们不期望它被修改,所以要加const进行修饰;还需要指定拷贝num字节的值,即num要为非负数,为了避免传入进来的num是一个负数,可以将num定为size_t类型,memcpy返回的是目标空间的起始地址,即返回类型我们也定为void* 。

                函数体:首先用assert断言判断传入进来的是否为空指针;void* 类型的指针不可以直接解引用,这里的num是指字节数,不同的数据类型所占的字节数不同,所以最好一个一个字节访问,即将 void* 强转成 char* (解引用时一次访问一个字节)类型;每访问一个字节后就自增一,拷贝完成后,这时的dest已经不再指向首元素地址,所以在这之前要创建一个void* 的指针记录dest,最后返回记录dest的指针即可。

                模拟代码:

                #include
                #include
                void* my_memcpy(void* dest, const void* src, size_t num)
                {
                	assert(dest && src);
                	void* ret = dest;
                	while (num--)
                	{
                		*(char*)dest = *(char*)src;
                		src = (char*)src + 1;
                		dest = (char*)dest + 1;
                	}
                	return ret;
                }
                int main()
                {
                	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
                	int arr2[20] = { 0 };
                	my_memcpy(arr2, arr1, 20);
                	for (int i = 0; i  
                

                【C语言基础】:内存操作函数 第3张

                注意:memcpy函数不可以拷贝重叠的内存块(虽然也能实现)但不安全,对于重叠的内存块,memmove是一种更安全的方法。

                二、memmove函数的使用和模拟实现

                函数原型:

                void * memmove ( void * destination, const void * source, size_t num );
                

                移动内存块

                1. 将num字节的值从源指向的位置复制到目标指向的内存块。复制就像使用了中间缓冲区一样进行,从而允许目标和源重叠。
                2. 源指针和目标指针所指向的对象的底层类型与此函数无关;结果是数据的二进制副本。
                3. 该函数不检查源中是否有任何终止null字符——它总是精确地复制num个字节。
                4. 为了避免溢出,目的参数和源参数所指向的数组的大小至少为num字节。

                memcpy与memmove的区别就在于memmove可以复制重叠的内存块。

                2.1 memmove函数的使用

                【示例】:将arr1中的1,2,3,4,5这几个元素拷贝到arr1中的3,4,5,6,7的位置。

                #include
                #include
                int main()
                {
                	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
                	memmove(arr1 + 2, arr1, 5 * sizeof(int));
                	for (int i = 0; i  
                

                【C语言基础】:内存操作函数 第4张

                2.2 memmove函数的模拟实现

                【C语言基础】:内存操作函数 第5张

                模拟思路:

                函数参数和返回类型:和memcpy函数一致,这里就不多作介绍了。

                函数体:这里总体要分两种情况:一种是destsrc;对于第一种情况,需要从前向后拷贝,对于第二种情况,需要从后向前拷贝,至于不重叠的话,无论是从前向后还是从后向前都是可以的。从前向后拷贝的方法和memcpy是一致的,这里就不多说了;从后向前拷贝也比较简单,src强转成 char* 之后加上num就是最后一个字节,然后num不断自减,就可以实现从后向前拷贝。

                模拟代码:

                #include
                #include
                void* my_memmove(void* dest, const void* src, size_t num)
                {
                	assert(dest && src);
                	void* ret = dest;
                	if (dest 后
                		while (num--)
                		{
                			*(char*)dest = *(char*)src;
                			src = (char*)src + 1;
                			dest = (char*)dest + 1;
                		}
                	}
                	else {
                		// 后-->前
                		while (num--)
                		{
                			*((char*)dest + num) = *((char*)src + num);
                		}
                	}
                	return ret;
                }
                int main()
                {
                	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
                	my_memmove(arr1 + 2, arr1, 5 * sizeof(int));
                	for (int i = 0; i  
                

                【C语言基础】:内存操作函数 第6张

                三、memset函数的使用

                函数原型:

                void * memset ( void * ptr, int value, size_t num );
                

                填充内存块

                将ptr指向的内存块的前num个字节设置为指定的值(解释为unsigned char)。

                参数说明:

                ptr

                指向要填充的内存块的指针。

                value

                需要设置的值。该值作为int类型传递,但函数使用该值的unsigned char转换来填充内存块。

                num

                要设置为该值的字节数。size_t是一个无符号整型。

                3.1 menset函数的使用

                【示例】:将arr数组中的hello替换成x

                #include
                #include
                int main()
                {
                	char arr[] = "hello world";
                	memset(arr, 'x', 5);
                	printf("%s\n", arr);
                	return 0;
                }
                

                【C语言基础】:内存操作函数 第7张

                注意:这里的num指的是该值的字节数。

                四、memcmp函数的使用

                函数原型:

                int memcmp ( const void * ptr1, const void * ptr2, size_t num );
                

                比较两个内存块

                将ptr1所指向的内存块的前num字节与ptr2所指向的前num字节进行比较,如果它们都匹配则返回0,如果不匹配则返回不同于0的值,表示哪个值更大。

                参数说明:

                ptr1

                指向内存块的指针。

                ptr2

                指向内存块的指针。

                num

                要比较的字节数。

                注意:与strcmp不同,该函数在找到空字符后不会停止比较。

                return value(返回值)indicates(含义)
                0在两个内存块中不匹配的第一个字节在ptr1中的值大于ptr2中的值(如果作为unsigned char值计算)
                4.1 memcmp函数的使用

                【示例】:比较arr1数组和arr2数组中前16个字节;在比较前17个字节。

                #include
                #include
                int main()
                {
                	int arr1[] = { 1,2,3,4,5,6,7 };
                	int arr2[] = { 1,2,3,4,8,8,8 };
                	int ret1 = memcmp(arr1, arr2, 16);
                	int ret2 = memcmp(arr1, arr2, 17);
                	printf("%d\n", ret1);
                	printf("%d\n", ret2);
                	return 0;
                }
                

                【C语言基础】:内存操作函数 第8张

                【C语言基础】:内存操作函数 第9张

                分析:一个整型占4个字节,比较前16个字节就是比较前4个元素,前4个元素都是一样的,所以返回0。但从17个字节开始,arr1和arr2数组就开始不同了,arr1是05,而arr2是08,08大于05,所以返回-1。


免责声明
1、本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明。
2、本网站转载文章仅为传播更多信息之目的,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所
提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何
损失或损害承担责任。
3、任何透过本网站网页而链接及得到的资讯、产品及服务,本网站概不负责,亦不负任何法律责任。
4、本网站所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在
转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并白负版权等法律责任。

手机扫描二维码访问

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,2306人围观)

还没有评论,来说两句吧...

目录[+]