创建数组的三种方式
①声明一个数组,声明时用常量表达式指定数组维数,然后使用数组名访问数组元素。
int array[5];
②声明一个变长数组,声明时用变量表达式指定数组维数,然后使用数组名访问数组元素。
int n = 5;
int array[n]; // 注意:C99标准下才可以喔。
③声明一个指针,调用malloc(),然后使用该指针访问数组元素。(需要引入头文件 <malloc.h>)
int * array ;
array = (int * ) malloc(5 * sizeof(int)); // 5 个连续的地址
或者
int n = 5;
int * array ;
array = (int * ) malloc(n * sizeof(int)); // // n 个连续的地址。 注意:C99标准下才可以喔。
malloc
malloc( ) 可以在程序运行时分配更多的内存。这些内存就是堆。
参数:所需内存字节数。根据申请的块数量和指针的类型进行计算。
malloc( 5 * sizeof(int)); // 申请 5 个 int 型的数据的地址
malloc( ) 将找到可用内存中一个大小适合的块。
返回:那块内存第一个字节的地址。因为默认返回 void * 型,所以要根据指针的类型进行强制转换。 (如果找不到合适的空间,则返回空指针)
int * array = (int * ) malloc(5 * sizeof(int)); //强制转换成 int * 型的地址
因此,我们可以把这个地址赋给一个指针变量,并使用这个指针来访问那一块内存。
free
free( ) 释放 malloc( ) 分配的内存
当用malloc申请一段内存,在使用完毕之后应该用free将这段内存释放掉。(一个malloc对应一个free)
例如:
int* array = (int*)malloc(5 * sizeof(int));
free(array);
这里的free并不是真的将这段内存杀死掉,而是将这段内存标记为可用内存,也就是说,当free掉这段
内存之后,这段内存是可以被自由调用的,或可以被某一次malloc申请到。
但free之后array仍然是指向这段内存的地址,而且这段内存的数据也没有被覆盖,如果你某一次用指针
p用malloc申请到了与array同样的地址,那么你操作了array指针后,同样也操作了p指针,出现冲突情
况。
所以为了避免这样的情况发生,应该在free掉array之后,将array指向NULL,这样之后就不会发生指针
数据冲突的情况了。
free(array);
array = NULL;
#include<stdio.h>
#include<malloc.h>
using namespace std;
int main(){
int * array; //声明指针
array = (int*)malloc(5 * sizeof(int)); //申请内存
for(int i= 0;i<5;i++){
array[i]=i; //赋值
}
free(array); //释放内存
array = NULL;
return 0;
}
关于指针
在上面,我们用malloc来给一个指针开辟了指定大小的内存空间 (初始化),使得这个指针可以用来赋值。
如果不用malloc而直接对指针进行取值会怎么样呢?
int * array; //未初始化的指针
*array = 5 ;
运行结果:程序直接崩掉。
当创建一个指针时,系统只分配了用来存储指针本身的内存空间,并没有分配用来存储数据的内存空间,所以在这种情况下对指针进行赋值将会导致程序的崩溃。
另外,我们在函数中,或者for、while中通常不用malloc给指针变量开辟空间,而是直接 type*,例如下
{
int a =1;
int* p = &a;
}
当函数写完的时候,我们并不需要去free这个指针,因为当函数的生命周期结束后,这些指针变量会由系统自己释放掉,除非这个指针变量存储着malloc动态申请的内存。因为,函数的参数与内部所定义的变量都是栈上的内存,而malloc动态申请的内存是堆上的。栈的空间会自动释放,而堆里的空间必须手动free释放。
参考书籍:
《C Primer Plus (第五版)》Stephen Prata 云巅工作室译
《C++面向对象程序设计 (第二版)》谭浩强