【C】内存操作函数

本文详细介绍了C语言中的字符串遍历方法(for循环和指针)、内存拷贝函数memcpy与memmove的区别与使用、以及memcmp和memset的基本概念和应用。特别强调了内存操作中的注意事项和重叠拷贝问题。
摘要由CSDN通过智能技术生成

目录

1、字符串遍历

(1)for循环遍历

(2)指针遍历

2、memcpy 不重叠内存拷贝

模拟实现思路

模拟实现注意点

(重叠拷贝)

3、memmove 重叠内存拷贝 

模拟实现

模拟实现注意点

4、memcmp 内存比较

5、memset 内存块填充


1、字符串遍历

(1)for循环遍历

	char arr[20] = "abcdefghijklmn";

	int n = strlen(arr);
	for (int i = 0; i < n-1; i++)
	{
		printf("%c", arr[i]);
	}
	printf("\n");

(2)指针遍历

此处p++不能放在while循环中,因为后置++,会导致第一次打印时从第二个字符开始打印 ;

若字符串以字符数组构成,char arr1[4]={'a','b','c','\0'};用指针遍历,字符数组末尾必须添加'\0',否则指针会向外访问变成野指针;

    char* p = arr;
	while (*p)
	{
		printf("%c", *p++);
	}
	printf("\n");

 

2、memcpy 不重叠内存拷贝

函数解释:void* memcpy(void* destination, void* sorse, size_t num);将num字节的值,从源指向的位置直接复制到目标指向的内存空间;memcpy不关心内容,即会拷贝'\0';memcpy用来处理不重叠的内存拷贝;

模拟实现思路

1、从源src指向的位置拷贝任意类型的内容到dest指向的内存空间中,最后返回目的地空间;所以这里不知道会传递什么类型的数组的地址,参数设置为void*类型;2、进入函数内部,对源指针解引用赋值给解引用目的地指针;但此处不能对void*类型的指针直接解引用和进行指针与运算,所以需要对指针类型强转;3、考虑到复制的num字节数可能极小,可能为奇数,所以指针类型强转为char*最合适,力度最小最精细;

模拟实现注意点

1、强转在语句中是临时的,所以不能在强转语句后 后置++,强转完成后++时强转已经失效;2、比如*((char*)dest); dest++;此时强转已失效,dest为void*类型,void*类型指针不能进行指针运算++;3、修改代码为dest=(char*)dest+1;4、此时整形6在内存中存储时,06 00 00 00,所以此时访问21个字节,有效访问到06

#include<stdio.h>
#include<string.h>

void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret=dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
        //或者 *((char*)dest)++ = *((char*)src)++;

	}
	return ret;;
}

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int arr2[15] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,'\0'};
	my_memcpy(arr2, arr1, 21);

	//for (int i = 0; i < 15; i++)
	//{
	//	printf("%d ", arr2[i]);
	//}
	
	int* p = arr2;
	while (*p)
	{
		printf("%d ", *p);
		p++;
	}
	return 0;
}

(重叠拷贝)

    int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };若想将{ 1,2,3,4,5 }拷贝到{ 3,4,5,6,7 }处,此时内存重叠;将1拷贝到3处,3即被覆盖,无法实现拷贝;

但在有的编辑器上,memcpy可实现重叠拷贝,即memmove的功能;

3、memmove 重叠内存拷贝 

void* memmove(void* dest, const void* src, size_t num);

memmove(100分)函数功能同memcpy(60分)一致,但比memcpy更强大,能拷贝重叠的内存;

模拟实现

#include<stdio.h>
#include<assert.h>

void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	if (dest < src)   //前->后
	{
		while (num--)
		{
			*(((char*)dest)++) = *(((char*)src)++);
		}
	}
	else   //后->前
	{
		while (num--)
		{
			*(((char*)dest) + num) = *(((char*)src) + num);  
			//此时num已减一,指针跳过了num-1个字节,指向了第num个字节
		}
	}
	return ret;
}

int main()
{
	int arr[10] = { 1,2,3,4,5, 6,7,8,9,0 };
	my_memmove(arr + 2, arr, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

模拟实现注意点

1、首先模拟思路是:根据源与目的指针的位置,分为两种不同的拷贝方式;2、dest<src,源指针在目的指针后,若重叠,则重叠部分在源指针前半部分,先拷贝重叠部分,源从前往后拷贝;拷贝时,强转为字符指针,字符指针+1跳过一个字符即一个字节,所以可用num--逐个字节拷贝;注意强转的临时性;2、src<dest,重叠在源后半部分,从后往前拷贝指针跳过num-1个字节,指向第num个字节,此时倒着拷贝找到最后一个字节是关键;3、注意num--循环num次,--num循环num-1次;4、memcpy库函数在vs编译器上可以实现重叠拷贝,但不代表其他编译器上的效果,重叠拷贝用memmove最适合;5、if else是条件语句,函数只会进入一种情况,所以可用同一num,不会互相影响;

4、memcmp 内存比较

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

比较ptr1和ptr2所指向内存的前num个字节的内容;大于返回大于1的值,小于返回小于1的值,等于返回0;

函数使用举例:比较两数组首元素地址起的 前9个字节;

5、memset 内存块填充

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

ptr所指向的内存空间的前num个字节的内容修改为value值;即逐字节修改,不可逐元素修改;

使用举例1:将arr1数组,从首元素起,前8个字节的值,修改为1

函数使用举例2:将arr2数组,从第二个元素地址起,前4个字节的值,修改为n 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值