C语言内存管理(堆heap)
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- C语言内存管理(堆heap)
- 1.malloc
- 2.void free(void* ptr)
- 3.calloc 开辟空间(malloc)+初始化空间值为0
- 4.realloc 扩容
- 5.memcpy 用于拷贝二块独立空间的数据
- 6.memove 用于拷贝二块有重叠空间的数据
- 7 内存数据比较 memcmp
- 8 内存块初始化 memset
- 9注意:memxx接口都是按字节为单位处理的 会导致部分异常
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 );
- 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的
- 如果源空间和⽬标空间出现重叠,就得使⽤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来解释,则结果应该是个很大的数。