C语言的动态分配内存和内存拷贝等操作

C语言内存管理(堆heap)

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


1.malloc

(void*) 可以转化为任意类型的指针 可以转换长结构体指针,函数指针,数组指针等等

void* malloc(size_t size); size为字节空间
(1)开辟一块空间,返回该空间的起始地址;
(2)开辟失败,返回NULL;

int mian()
{
	int arr[10] = {0};
	int* p = (int*)malloc(40);
	if(p==NULL)
	{
		printf("%s\n",streeror(errno))
		retrun;
	}
	int i=0;
	for(i=0;i<10;i++)
	{
		(*p)=i;
		p++;
	}
	
}

2.void free(void* ptr)

(1)free是释放malloc开辟出来的空间,但不会对指针ptr做出任何改变
(2)ptr=NULL时,函数什么也没做;
注意:free之后,要把ptr置为NULL;

3.calloc 开辟空间(malloc)+初始化空间值为0

void* calloc(size_t num,size_t size)
开辟num个元素,每个元素占用size个字节,开辟这样一块空间
calloc(10,sizeof(int)); 开辟10个元素,没有元素int个字节,4字节 一个10*4=40字节

4.realloc 扩容

void* realloc(void*ptr,size_t size)
(1)改变一块空间的内存大小,改变后的空间为size个字节;
(2)返回的为新空间的地址。

5.memcpy 用于拷贝二块独立空间的数据

void* memcpy(void* destination,const void* source, size_t num);
(1)从source位置复制num个字节到destion的内存位置
(2)void* source num 限制的是原空间
(3)如果source和destination有重叠,复制的结果是未定义的
注意:这个函数遇到 '\0’不会停下来

void* my_memcpy(void* dest,const void* src, size_t num)
{
	assart(des&&src);
	void* ret = dest;
	while(num--)
	{
		*(char*)dest = *(char*)src;
		dest =(char*)dest + 1;
		src = (char*)src + 1;
	}
	retrun ret;
}

6.memove 用于拷贝二块有重叠空间的数据

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

  1. 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的
  2. 如果源空间和⽬标空间出现重叠,就得使⽤memmove函数处理
    在这里插入图片描述
#include <string.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
	int arr1[20] = { 0 };
//从3开始拷贝三个元素到1往后三个元素的位置
	memmove(arr, arr+2, 12);  //12表示12个字节数 此处等于3个int元素
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
}
#include <stdio.h>
#include <assert.h>
#include <string.h>
void* in_memove(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);

	if (dest<src)
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			((char*)dest)++;
			((char*)src)++;
		}
	}
	else
	{
		while (num--)
		{
			*(*(char*)dest+num) = *((char*)src + num);
		}
	}
	return ret;
}

7 内存数据比较 memcmp

int memcmp(const void *str1, const void *str2, size_t n)
(1)比较二个元素
(2)相减方式来实现的

int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	assert(ptr1 && ptr2);//用断言判断ptr1和ptr2是否为空指针
 
	//类型转换
	const char* p1 = (const char*)ptr1;
	const char* p2 = (const char*)ptr2;
 
	while (num && (*p1 == *p2))
	{
		num--;
		p1++;
		p2++;
	}
 
	// num 为 0 时,两者相等
	return (0 == num) ? 0 : *p1 - *p2;
}

8 内存块初始化 memset

void *memset(void *s, int c, size_t n);
memset() 函数将指定的值 c 复制到 str 所指向的内存区域的前 n 个字节中,这可以用于将内存块清零或设置为特定值
注意事项
1.memset() 的第二个参数 value 通常是一个 int 类型的值,但实际上只使用了该值的低8位。这意味着在范围 0 到 255 之外的其他值可能会产生未定义的行为。
2.num 参数表示要设置的字节数,通常是通过 sizeof() 或其他手段计算得到的。

#include <stdio.h>
#include <string.h>
 
int main ()
{
   char str[50];
 
   strcpy(str,"This is string.h library function");
   puts(str);
 
   memset(str,'$',7);
   puts(str);
   
   return(0);
}

9注意:memxx接口都是按字节为单位处理的 会导致部分异常

例子:

int a[10];
memset(a,0,sizeof(int)*10);//为0
memset(a,1,sizeof(int)*10); //为3368018
memset(a,1,sizeof(int)*10); //为446827X

why?
注意:memxx是按照字节来进行处理的,char a=0;一个字节为1,二进制表示00000001,一个int a=0,应该是00000000 00000000 00000000 00000001,而按照char保存,则结果为00000001 00000001 00000001 00000001 ,安装int来解释,则结果应该是个很大的数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值