指针和动态存储分配
1 指针
指针是C语言的基本概念,每种数据类型都有相应的指针类型。指针类型变量存放的值实际上就是内存地址。指针的最基本操作:
& 取地址
* 去引用(间接引用)
如:
int i, *pi //其中 i 是整型变量,pi 是指向整数的指针。
pi = &i ; //则 &i 返回i的地址并把它赋值给 pi ,若要给 i 赋值,可以写成 i = 10 ; 或者 *pi = 10 ; pi 之前的 * 是去引用 , 10 并未存放指针里而是存放到 pi 所指向的存储单元。
NULL //表示空指针,不指向变量也不指向函数,可以用整数值0表示,C中NULL是一个宏,定义常量值 0 ;在关系表达式中可以表示‘假’
测试语句: if (pi == NULL) 或者 if (!pi)
2 动态存储分配
程序1.1 分配、释放内存空间
int i , *pi ;
float f , *pf ;
pi = (int *)malloc(sizeof(int)) ; //这里缺少判断,如果存储空间不足将会申请失败
pf = (float *)malloc(sizeof(float)) ;
*pi = 1024 ;
*pf = 3.14 ;
printf("an_integer_ = _%d,_a_float_ =_%f\n",*pi,*pf) ;
free(pi) ;
free(pf) ;
替换malloc的相应代码:
if ((pi = (int*)malloc(sizeof(int))) == NULL || (pf = (float*)malloc(sizeof(float))) == NULL)
{
fprint(stderr, "Insuffcient _ memory") ;
exit(EXIT_FALLURE) ;
}
或者用以下等价代码:
if (!(pi = (int*)malloc(sizeof(int))) || !(pf = (float*)malloc(sizeof(flota))))
{
fprint(stderr, "Insuffcient _ memory") ;
exit(EXIT_FALLURE) ;
}
因为在程序当中malloc在程序中经常应用,方便的做法就是定义宏语句
#define MALLOC(p,s) \
if (!(p = malloc(s)))
{
fprint(stderr, "Insuffcient _ memory") ;
exit(EXIT_FALLURE) ;
}
现在就可以替换1.1程序中的malloc语句
MALLOC(pi , sizeof(int)) ;
MALLOC(pf , sizeof(float));
在1.1程序printf语句之后插一行:
pf = (float *)malloc(sizeof(float)) ;
现指针指向的存储空间不再是存放3.14的存储单元。现在无法在访问原来那块存储空间。这是悬空引用的一个例子。只要指向动态存储区域的指针丢掉了,原存储区域对程序而言就丢掉了。需要牢记一点,如果不再需要一块动态存储空间,那么一定要把它还给系统。
C程序中将所有尚未指向的指针都取NULL是好习惯。
另一个好习惯是,在转换指针类型时,应该显示的使用强制类型转换。如:
pi = malloc(sizeof(int)) ; //assign to pi a pointer to int
pf = (float*) pi ; //casts an int pointer to a float pointer