作为例子,下面的代码演示了最简单的使用堆的方法:
int main()
{
int *p;
p = (int *)malloc(sizeof(int));
if (p==0)
{
printf("错误:内存不足n");
return 1;
}
*p=5;
printf("&dn", *p);
free(p);
return 0;
}
程序的开始调用了malloc函数,这个函数做了三件事:

接着程序用if (p==0)检查指针p以确定分配申请成功(此行也可写成if (p==NULL)甚至if (!p))。如果分配失败(p等于零),则程序终止,否则程序将分配的内存块初始化为5,然后打印内存块的值,接着调用free函数将内存块返还给堆,最后退出。
前面的章节有一段代码是将p赋值为一个现成整数i的地址,而本例中的代码和那段代码实际上并无不同。区别只是在于:对于变量i的内存,它是程序预分配内存空间的一部分,有两个名字i和*p;而对于从堆上分配的内存,它只有一个名字*p,且是在程序运行中分配的。两个常见的问题是:
void main()
{
int*p, *q;
p=(int *)malloc(sizeof(int));
q=p;
*p=10;
printf("%dn", *q);
*q=20;
printf("%dn", *q);
}
此程序的最后输出结果是代码第4行打印的10和代码第6行打印的20。下面是一个内存状态示意图:

下面这个程序稍有不同:
void main()
{
int *p, *q;
p=(int *)malloc(sizeof(int));
q=(int *)malloc(sizeof(int));
*p=10;
*q=20;
*p=*q;
printf("%dn", *p);
}
此程序的最后输出结果是代码第6行打印的20。下面是它的内存状态示意图:

注意,编译器会接受*p=*q,因为*p和*q都是整数。这条语句的意思是说:“将q指向的整数传送到p指向的整数中去。”被传送的是数值。编译器也会接受p=q,因为p和q都是指针且指向相同的类型(若s为指向字符的指针则p=s是不允许的,因为它们指向不同类型)。p=q这条语句的意思是说:“将p指向和q相同的内存位置。”换句话说,q指向的地址被传送到了p,因此两个指针指向相同的地址。被传送的是地址。
从这些例子可以知道,初始化指针的方式有四种。在程序中声明一个指针时(如int *p),它开始处于未初始化状态。它可能指向任何位置,因此对它的解引用(取出指针指向的地址中的内容)是错误的。初始化指针就是将其指向一个已知的内存地址。
p=0;
或:
p=NULL;
此语句完成的操作是将零赋给p。指针p指向的地址为零。一般用下面的示意图表示这种情况:

if (p==0)
{
...
}
或:
while (p!=0)
{
...
}
系统会识别零值,如果您无意中解引用一个零指针,系统会报错。例如下列代码:
p=0;
*p=5;
程序一般会崩溃。指针p不指向内存块而是零地址,所以不能为*p赋值。后面我们讲到链表时,零指针将被作为一个标志使用。
malloc命令用于分配一个内存块。当此内存块不再需要时还可以将其释放。释放的内存块可以被后来的malloc语句重新分配,这样系统就可以回收内存。释放内存的命令叫做free,它接受一个指针作为参数。free命令完成两件事情:
下例显示了如何使用堆。它分配了一块整数内存,写入数据然后输出,最后废除此内存块:
#include
int main()
{
int *p;
p=(int *)malloc (sizeof(int));
*p=10;
printf("%d
free(p);
return 0;
}
此代码其实只适用于在C中演示分配、使用和释放内存块的过程。malloc用于分配一块指定大小的内存,本例中是sizeof(int)字节(4字节)。C语言的sizeof命令以字节为单位返回任何类型的大小。代码中完全可以写成malloc(4),因为在大部分机器上sizeof(int)等于4个字节。但是使用sizeof可以大大增强代码的可移植性和可读性。
malloc函数返回一个指向被分配内存块的指针。这是一个通用指针,若不经类型转换即使用一般会导致编译器发出类型警告。类型转换(int *)将malloc返回的通用指针转换为一个“指向整数的指针”,即与p一致。C中的free语句将内存块返还给堆以供重新使用。
第二个例子说明的函数和前一例相同,但是用结构体代替了整数。C代码如下:
#include
struct rec
{
int i;
float f;
char c;
};
int main()
{
struct rec *p;
p=(struct rec *) malloc (sizeof(struct rec));
(*p).i=10;
(*p).f=3.14;
(*p).c='a';
printf("%d %f %c
free(p);
return 0;
}
请注意这行:
(*p).i=10;
很多人不明白为什么不能写成:
*p.i=10;
答案是这和C语言的操作符优先级有关。5+3*4的结果是17,不是32,因为在大多数计算机语言中*比+有更高的优先级。C语言中,操作符.比*有更高的优先级,所以要使用括号保持正确的操作顺序。
但是大部分人觉得总是输入(*p).i太麻烦了,因此C提供了一种简洁记法。下面的两条语句完全等效,而第二条的输入更加简便:
(*p).i=10;
p->i=10;
阅读别人代码的时候,您会发现第二种记法比第一种更常用。
编辑推荐