数组 就是变量的有序集,因此只有可以动态的创建一个变量,就可以动态的创建多个变量了,
堆空间就是一片内存区域,用于动态创建内存变量的区域
void 类型是基础类型,不是基础数据类型,为什么?因为没有办法 使用 void 类型创建一个变量,
void 只能用来声明一个函数没有返回值,或者没有参数,除此之外没有别的用处了 ?
错觉 , 可以使用void 类型,来扩展成这样的指针类型 void*
如果我们希望从一个指针从内存当中取数据,必须知道取多少字节的数据
假设 int* p (每次读内存的时候,读4个字节的数据),将四个字节内存中的数据拿出来,当作一个整型使用
如果 p 是这样的类型 void* p ?
可以保存起始地址,但是却没有办法读具体的数据了,因为 void 无长度信息,
void* 是一个合法的指针类型,但是却无法用 void* 类型的指针 来访问具体的内存数据,
因为 p 是 void* 类型的指针,意味着这种类型的指针,它可以保存任意类型的地址,因为这里的赋值语句都是正确的
printf("&f\n", *p) 这种写法错误,因为不可能使用 void* 类型的指针来访问内存中的数据,因为void 类型不具备长度信息,
char 代表的长度信息是 1 字节,int 4 字节, float 4 字节, double 8字节,所以这些基础的数据类型所扩展出来的指针,都能够访问数据出来,而void 不具备长度信息,没有办法使用void 扩展出来的指针去访问内存中的数据
编译器没有错误,意味着,这 4 条语句都是合法的
使用 p 指针访问内存中的数据?
出现错误,表示 不能够使用 void* 类型的指针,去访问内存中的数据
如果非要访问内存中的数据怎么办?
赋值符号左右两边的类型不一样 不同的指针类型
编译结果告诉我们这里有问题, 所以,具体数据类型的指针之间,不能够相互的乱赋值,void*是一个特殊的类外
void* 代表一个地址 ,这个地址就是我们所申请的内存的起始地址,
怎么归还,调用 free函数, 将之前申请到的内存的起始地址作为参数,调用 free 函数,就可以了
参数的这个 p 指针 所代表的地址,必须是堆空间中的地址,
如果非要用一个全局数据区里面的地址调用free,或者用一个栈空间区里面的地址调用free, 程序在后面的运行中会崩溃,free 所要释放的是堆空间
这里定义了一个指针 p , 这个指针 p 想要指向 int 类型的变量,具体指向哪个int 类型变量,p 是指向了堆空间里面的 4 个字节,换句话说,p 指向了int 类型的变量存在于 堆空间中,
*p = 100; 把 p 所指向的堆空间里面的 4 个字节 赋值为 100,将4 个字节的堆空间当成一个 int 来使用
编译无误意味着这里的申请成功了,我们拿到了4 个字节的堆空间,并把这 4 个字节的堆空间当作int 类型的变量来使用
malloc -- -- -- -- 从堆空间里面申请内存,申请16 字节的内存,就是想申请 4 个int 类型的变量,换句话说这里想申请一个数组,这个数组存在于堆空间当中,这个数组里面有4 个int ,起始地址被 p 所指向,
申请堆空间之后,如果不再使用了,必须归还
如果申请结果为 NULL (空),证明堆空间已经耗尽了
多次释放申请到的内存,会导致程序运行不稳定
malloc 申请到的东西只是这一片内存的起始地址,所以返回值是 void* 类型