C语言 内存函数

目录

前言

一、memcpy()函数

二、memmove()函数

三、memset函数

四、memcmp()函数

总结


前言

在C语言中内存是我们用来存储数据的地址,今天我们来讲一下C语言中常用的内存函数。


一、memcpy()函数

memcpy()函数与我们之前讲的strcpy()函数类似,只不过memcpy()不单单可以用与字符串的复制,可以复制内存中的各种数据类型。函数语法定义:

cpp 复制代码
void * memcpy ( void * destination, const void * source, size_t num );

• 函数 memcpy 从 source 的位置开始向后复制n um 个字节的数据到 destination 指向的内存位置。
• 这个函数在遇到 '\0' 的时候并不会停下来。
• 如果source和destination有任何的重叠,复制的结果都是 未定义 的。

cpp 复制代码
#include <stdio.h>
#include <string.h>
int main()
{
    int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr2[10] = { 0 };
    memcpy(arr2, arr1, 20);//20为复制的字节总大小
    int i = 0;
    for (i = 0; i < 10; i++)
 {
       printf("%d ", arr2[i]);
 }
   return 0;
}

虽然memcpy函数也可以实现重叠,但是对于重叠的内存,我们都是交给memmove函数来处理。

函数模拟实现:

cpp 复制代码
void* memcpy(void* dst, const void* src, size_t count)
{
	void* ret = dst;
	assert(dst);
	assert(src);
	/*
	* copy from lower addresses to higher addresses
	*/
	while (count--) {
		*(char*)dst = *(char*)src;
		dst = (char*)dst + 1;
		src = (char*)src + 1;
	}
	return(ret);
}

由于不知道输入的数据类型,我们都是一个字节一个字节开始传输的,所以对地址继续强制类型转换为char *。

二、memmove()函数

memmove函数与上面memcpy函数类似,只不过处理的是重叠的内存。函数语法定义:

cpp 复制代码
void * memmove ( void * destination, const void * source, size_t num );

• 和 memcpy 的差别就是 memmove 函数处理的源内存块和目标内存块是可以重叠的。
• 如果源空间和目标空间出现重叠,就得使用 memmove 函数处理。

cpp 复制代码
#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr1 + 2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}


函数的的模拟实现:
有2种情况:
dest在sourc之后

所以我们需要从后往前复制,比如5->7 4->6 3->5 2->4 1->3,这样交换就不会数据丢失。
dest在source之前:

这时我们就要从前往后复制了,比如3->1,4->2,5->3,6->4,7->5,这样就不会覆盖之前的元素了。

cpp 复制代码
void* memmove(void* dst, const void* src, size_t count)
{
	void* ret = dst;
	if (dst <= src || (char*)dst >= ((char*)src + count)) {
		//从前往后复制
		while (count--) {
			*(char*)dst = *(char*)src;
			dst = (char*)dst + 1;
			src = (char*)src + 1;
		}
	}
	else {
	    //从后往前复制
		dst = (char*)dst + count - 1;
		src = (char*)src + count - 1;
		while (count--) {
			*(char*)dst = *(char*)src;
			dst = (char*)dst - 1;
			src = (char*)src - 1;
		}
	}
	return(ret);
}

三、memset函数

memset()函数的作用时给设置内存的,将内存中的值以字节为单位设置成想要的内容。

函数语法定义:

cpp 复制代码
void * memset ( void * ptr, int value, size_t num );
cpp 复制代码
#include<stdio.h>
#include<string.h>

int main()
{
	char str[] = "hello world";
	memset(str, 'x', 6);
	printf(str);
	return 0;
}


注意:由于 memset是每个字节每个字节进行设置的,所以对于整型元素的设置,可能达不到我们想要的效果。

cpp 复制代码
#include<stdio.h>

int main()
{
	int a[10] = {0};
	memset(a,1,10 );
	int i = 0;
	for (i = 0; i < 10; i++) {
		printf("%d ", a[i]);
	}
	return 0;
}

输出:

我们想把整型数组元素都设置为1,但是结果却不是我们想要的。因为memset函数是每个字节设置的,在数组中的元素在内存中为:

我们发现memset函数是每个字节都设置为1,所以不是我们想要的。

四、memcmp()函数

memcmp函数比较内存中数据大小,函数语法定义:

cpp 复制代码
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

• 比 较从 ptr1 和 ptr2 指针指向的位置开始,向后的 num 个字节
• 返回值如下:


函数模拟实现:

cpp 复制代码
int my_memcmp(const void* ptr1, const void* ptr2, size_t num){
	assert(ptr1&& ptr2);
	char* p1 = ptr1;
	char* p2 = ptr2;
	size_t count = num;
		while (*p1==*p2)
		{
			if (num == count) {
				break;
			}
			if (*p1 == '\0');
			return 0;
			p1++;
			p2++;
			count++;
		}	
	return *p1 -*p2;
}

总结

上述文章讲了一些与内存有关的函数,希望对你有所帮助。

相关推荐
yqcoder3 分钟前
自定义脚手架
开发语言·javascript·node.js
Ciderw4 分钟前
Go的Slice底层数据结构和特性
开发语言·数据结构·c++·后端·面试·golang
七灵微7 分钟前
软件越跑越慢的原因分析
java·开发语言
羚羊角uou22 分钟前
【C++】详细讲解继承(上)
开发语言·c++
liwulin050643 分钟前
【JAVA】获取windows内存使用率排名前十的进程信息、总的cpu和内存使用率
java·开发语言·windows
马船长1 小时前
ASP.NET代码审计 SQL注入篇(简单记录)
开发语言·数据库·sql·网络安全·asp.net
怀旧6662 小时前
Servlet 详解
java·开发语言·servlet·个人开发
叫我阿呆就好了2 小时前
C++ 复习总结记录九
开发语言·c++
浪浪山小白兔2 小时前
深入理解JavaScript中的Location对象
开发语言·前端·javascript·html·html5
软件工程师文艺2 小时前
利用 Three.js 实现 3D 粒子正方体效果
开发语言·javascript·3d