动态对象被存储在栈中,当程序流离开对象所在的语句块时,动态对象的空间就会被释放。因此,只有对小的、临时的数组,定义长度可变数组才比较合理。如想动态地创建大型数组,通常应该使用标准函数 malloc()和 calloc()来显式地分配内存空间。
这种数组的存储周期会持续到程序结束,也可以调用函数 free()来主动地释放被占用的内存空间。
声明为 size_t 类型,从根本上防止它传递负数::
int *TestArray(size_t num,int value)
{
int *arr=NULL;
/越界检查(越上界)/
if(num<ARRAY_NUM)
{
arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
if(arr!=NULL)
{
arr[num]=value;
}
else
{
/处理arr==NULL/
}
}
return arr;
}
include <stdlib.h>
void malloc(unsigned long size);
malloc 函数只有一个形参,并且是整型。该函数的功能是在内存的动态存储空间即堆中分配一个长度为size的连续空间。函数的返回值是一个指向所分配内存空间起始地址的指针,类型为 void型。
简单的理解,malloc 函数的返回值是一个地址,这个地址就是动态分配的内存空间的起始地址。如果此函数未能成功地执行,如内存空间不足,则返回空指针 NULL
int *p = (int *)malloc(4);
它的意思是:请求系统分配 4 字节的内存空间,并返回第一字节的地址,然后赋给指针变量 p。当用 malloc 分配动态内存之后,上面这个指针变量 p 就被初始化了。
##跨函数使用动态内存”也可以不用多级指针,即直接返回被调函数中指向动态内存的指针变量,然后赋给主调函数中的指针变量就行了:
include <stdio.h>
include <stdlib.h>
int * DynamicArray(void) ; //函数声明
int main(void)
{
int *p = DynamicArray(); //函数调用
printf("*p = %d\n", *p);
return 0;
}
int * DynamicArray(void) //DynamicArray是“动态数组的意思”
{
int q = malloc(sizeofq);
*q = 5;
return q;
}
在 C 语言中,在讲动态内存分配之前经常有一句话,叫作“永远不要返回局部变量的地址”。
数组指针和指针数组的区别
首先,对于语句“intp1[5]”,因为“[]”的优先级要比“”要高,所以 p1 先与“[]”结合,构成一个数组的定义,数组名为 p1,而“int*”修饰的是数组的内容,即数组的每个元素。也就是说,该数组包含 5 个指向 int 类型数据的指针,如图 1 所示,因此,它是一个指针数组。
图 1
其次,对于语句“int(p2)[5]”,“()”的优先级比“[]”高,“”号和 p2 构成一个指针的定义,指针变量名为 p2,而 int 修饰的是数组的内容,即数组的每个元素。也就是说,p2 是一个指针,它指向一个包含 5 个 int 类型数据的数组,如图 2 所示。很显然,它是一个数组指针,数组在这里并没有名字,是个匿名数组。
int arr[5]={1,2,3,4,5};
int (*p1)[5] = &arr;
/下面是错误的/
int (*p2)[5] = arr;
其实原因很简单,在 C 语言中,赋值符号“=”号两边的数据类型必须是相同的,如果不同,则需要显示或隐式类型转换。在这里,p1 和 p2 都是数组指针,指向的是整个数组。p1 这个定义的“=”号两边的数据类型完全一致,而 p2 这个定义的“=”号两边的数据类型就不一致了(左边的类型是指向整个数组的指针,而右边的数据类型是指向单个字符的指针),因此会提示错误信息。