void指针

void用在函数定义中可以表示函数没有返回值或者没有形参,用在这里表示指针指向的数据的类型是未知的。

void*表示一个有效指针,它确实指向实实在在的数据,只是数据的类型尚未确定,在后续使用过程中一般要进行强制类型转换。

malloc()函数:动态分配内存空间

原型:void* malloc(size_t size);

作用:malloc()在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。如果希望在分配内存的同时进行初始化,请使用calloc()函数。

返回值:分配成功返回指向该内存的地址,失败则返回NULL

初始化:使用memset(str, 0, 20);初始化

#include<stdio.h>
#include<iostream>

int main(){
    //分配可以保存30个字符的内存,并把返回的指针转换为char*
    char *str = (char *)malloc(sizeof(char) * 30);
    str = "leetcode" ;
    cout << str << endl;
    return 0;
}

malloc背后的实现原理---内存池

malloc()和free()的分配算法:
image

内存池:

不管具体的分配算法是怎样的,为了减少系统调用,减少物理内存碎片,malloc()的整体思想是先向操作系统申请一块大小适当的内存,然后自己管理,这就是内存池(Memory Pool)。

调用malloc()发生了什么?

内存控制块数据结构,用于管理所有的内存块:is_available标志该块是否可用 + size标志该块的大小

实现malloc时要用到linux下的全局变量:指向进程堆底的指针,也就是指向堆中的第一个内存块 + 指向进程堆顶的指针,也就是指向堆中最后一个内存块的末地址。

1.对堆中的内存块进行遍历,找合适的内存块:判断该块是否可用;大小是否满足要求。

2.没有找到满足条件的内存块时:向操作系统申请新的内存块,返回内存块的首地址。

calloc()函数:分配内存空间并初始化

原型:void* calloc(size_t num, size_t size);

作用:calloc()在内存中动态分配num个长度为size的连续空间,并将每一个字节都初始化为0。所以它的结果是分配了num * size个字节长度的内存空间,并且每个字节的值都是0。

返回值:分配成功返回值指向该内存的地址,失败则返回NULL。

#include<iostream>
#include<stdio.h>
using namespace std;

int main(){
	//分配可以保存30个字符的内存,并把返回的指针转换为char*
	char *str = (char *)calloc(sizeof(char), 30);
	cout << str << endl;
	str = "leetcode" ;
	cout << str << endl;
	return 0;
}

realloc()函数:重新分配内存空间

原型:void* realloc(void* ptr, size_t size)

作用:realloc()对ptr指向的内存重新分配size大小的空间。如果size的值为0,那么ptr指向的内存空间就会被释放,但是由于没有开辟新的内存空间,所以会返回空指针;类似于调用free()

free()函数:

原型:void free(void* ptr);

作用:free()只能释放动态分配的内存,并不能释放任意的内存

注意:free()不会改变ptr变量本身的值,调用free()后它仍然会指向相同的内存空间,但是此刻内存已无效,不能被使用,所以建议将ptr的值设置为NULL。

posted on 2020-03-02 14:05  xiaobaizzZ  阅读(686)  评论(0编辑  收藏  举报