【C语言学习笔记---内存函数】

C语言进阶之内存函数

前言:
通过C语言进阶前篇的字符串函数的知识,继续C语言的内存函数学习。

/知识点汇总/
内存相关的函数
1.memcpy – strcpy —仅仅是操作字符串进行拷贝,而memcpy内存中的数据,不仅仅是操作字符
2.memmove
3.memset
4.memcmp — strcmp

1、memcpy函数

原型:void *memcpy( void *dest, const void src, size_t count ); ---- void 说明,兼容任意类型
头文件:<string.h>
功能:将源头内存的数据。拷贝到目标内存中
注意:与strncpy不同的是,参数num和count。一个是指需要拷贝的元素个数,一个是指需要拷贝的元素字节大小

#include <stdio.h>
#include <string.h>
int main()
{
    
    
	int arr1[10] = {
    
     0 };
	int arr2[] = {
    
     1,2,3,4,5 };
	memcpy(arr1, arr2, 20);//20 == 4*5
	int sz = sizeof(arr1) / sizeof(arr1[0]);
	for (int i = 0; i < sz; i++)
	{
    
    
		printf("%d ", arr1[i]);
	}
	return 0;
}

1.1、模拟实现memcpy

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

//注意:void* 不能进行运算操作
//另外,这里必须使用(char*)进行操作,因为如果是其它类型就会造成数据上的丢失等问题 --- 联想类似于qsort一个个字节进行操作
void* my_memcpy(void* dest, const void* src, size_t sz)//sz拷贝多少个字节
{
    
    
	assert(dest && src);
	while (sz--)//以一个字节一个字节的拷贝
	{
    
    
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;//注意:强制类型转换具备临时属性,所以需要(char*)dest+1来赋值保存数据,不能用dest++
		src =  (char*)src + 1;
	}
}

int main()
{
    
    
	int arr1[10] = {
    
     0 };
	int arr2[] = {
    
     1,2,3,4,5 };
	my_memcpy(arr1, arr2, 20);//20 == 4*5
	for (int i = 0; i < 5; i++)
	{
    
    
		printf("%d ", arr1[i]);
	}
	return 0;
}

扩展:memcpy对同一内存空间的操作问题

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

//注意:void* 不能进行运算操作
//另外,这里必须使用(char*)进行操作,因为如果是其它类型就会造成数据上的丢失等问题 --- 联想类似于qsort一个个字节进行操作
void* my_memcpy(void* dest, const void* src, size_t sz)//sz拷贝多少个字节
{
    
    
	assert(dest && src);
	void* ret = dest;
	while (sz--)//以一个字节一个字节的拷贝
	{
    
    
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;//注意:强制类型转换具备临时属性,所以需要(char*)dest+1来赋值保存数据,不能用dest++
		src = (char*)src + 1;
	}
	return ret;
}

int main()
{
    
    
	int arr[] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	//my_memcpy(arr+2, arr, 20);//20 == 4*5
	//模拟的memcpy达不到预期的要求
	memcpy(arr + 2, arr, 20);
	//发现库函数的memcpy可以实现要求
	for (int i = 0; i < 5; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
	return 0;
}

小结
1.memcpy只能对不同空间内存之间的数据进行操作
即:不重叠内存的拷贝,可以使用memcpy,而重叠的内存空间则需要用memmove函数
2.库函数可以实现,标准规定:
以memcpy来实现不重叠的内存的拷贝,且要求能达到60即可,以memmobe来实现重叠内存的拷贝
3.但是,发现当前的编译环境下,memcpy同样能实现重叠内存的拷贝,远远满足60分的要求,100分
所以于编译环境相关,建议相应的功能交给适合的函数实现即可。

2、memmove函数

原型:void *memmove( void *dest, const void src, size_t count ); ---- void 说明,兼容任意类型
头文件:<string.h>
功能:将源头内存的数据。拷贝到目标内存中,且与memcpy相比可以拷贝同一空间的数据

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

int main()
{
    
    
	//int arr1[10] = { 0 };
	//int arr2[] = { 1,2,3,4,5 };
	//memmove(arr1, arr2, 20);//20 == 4*5
	//int sz = sizeof(arr1) / sizeof(arr1[0]);
	//for (int i = 0; i < sz; i++)
	//{
    
    
	//	printf("%d ", arr1[i]);
	//}

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

2.1、模拟实现memmove函数

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

void* my_memmove(void* dest, const void* src, size_t sz)
{
    
    
	assert(dest && src);
	char* ret = (char*)dest;
	if (dest < src)//从前向后拷贝
	{
    
    
		while (sz--)
		{
    
    
			*((char*)dest) = *((char*)src);
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else//从后向前拷贝
	{
    
    
		while (sz--)//sz-- 先用再减,即先判断sz=20为真,用完后减1进入循环,此时sz=19
		{
    
    
			*((char*)dest + sz) = *((char*)src + sz);
		}
	}
	return ret;
}

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

3、memset函数

原型:void *memset( void *dest, int c, size_t count );
头文件:<string.h>
功能:是设置内存的,并且以字节为单位设置的

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

int main()
{
    
    
	char arr[] = "hello world";
	memset(arr+6, 'H', 4);
	printf("%s\n", arr);
	return 0;
}

建议:以字节为单位设置的,所以更合适字符,但是设置为0可以是任意类型

4、memcmp函数

原型:int memcmp( const void *buf1, const void *buf2, size_t count );
头文件:<string.h>
功能:是比较两个内存块,并且是以字节为单位的方式进行比较的
返回值
*buf1 > *buf2 — 返回>0的值
*buf1 = *buf2 — 返回=0的值
*buf1 < *buf2 — 返回<0的值

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

int main()
{
    
    
	//int arr1[] = { 1,2,3,4,5,6,7 };
	01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00
	//int arr2[] = { 1,2,3,7 };
	01 00 00 00 02 00 00 00 03 00 00 00 07 00 00 00
	//int ret = memcmp(arr1, arr2, 12);//精确到字节比较
	//printf("%d\n", ret);//0 --- 前12位相同

	//int arr1[] = { 1,2,3,4,5,6,7 };
	01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00
	//int arr2[] = { 1,2,3,7 };
	01 00 00 00 02 00 00 00 03 00 00 00 07 00 00 00
	//int ret = memcmp(arr1, arr2, 13);//精确到字节比较
	//printf("%d\n", ret);//-1 ---第十三位: 04 < 07

	int arr1[] = {
    
     1,2,3,4,5,6,7 };
	//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00
	int arr2[] = {
    
     1,2,3,0x11223304 };
	//01 00 00 00 02 00 00 00 03 00 00 00 04 33 22 11
	int ret = memcmp(arr1, arr2, 13);//精确到字节比较  --- 前13位相同 0
	//int ret = memcmp(arr1, arr2, 14);//精确到字节比较 --- 第14位 00 < 33 ---  -1
	printf("%d\n", ret);
	return 0;
}

5、结语

熟悉各个函数的使用有利于程序的可读性和效率,此篇笔记有误的地方请多多指教。
半亩方糖一鉴开,天光云影共徘徊。
问渠哪得清如许?为有源头活水来。–朱熹(观书有感)

猜你喜欢

转载自blog.csdn.net/m0_69455439/article/details/133219579