上一页 下一个

C编程的基础知识

动态数据结构:Malloc和Free

右边的块是malloc分配的内存块。

假设你想分配一定数量的内存执行期间您的应用程序。你可以随时调用malloc函数,并将请求从堆中一块内存。操作系统将保留一块内存为您的程序,你可以在任何你喜欢的方式使用它。当你完成了,你返回它回收通过调用操作系统的免费功能。其他应用程序可以储备后,供自己使用。

例如,下面的代码演示了最简单的堆的使用:

广告

int main () {int * p;p = (int *) malloc (sizeof (int));如果(p = = 0) {printf("错误:内存不足\ n ");返回1;}* p = 5;printf (" % d \ n”* p);自由(p);返回0;}

在这个程序中调用malloc函数的第一行。这个函数做三件事:

  1. malloc语句首先查看可用内存的数量在堆上,问道:“有足够的可用内存分配一块内存的大小要求?”的amount of memory needed for the block is known from the parameter passed into malloc -- in this case,sizeof (int)是4个字节。如果没有足够的可用内存,malloc函数返回地址0指示误差为零(另一个名称为空,你就会看到它C代码中使用)。否则malloc收益。
  2. 如果堆上的内存可用,系统“分配”或“储备”一块堆的大小指定。系统保留的内存块,它不是偶然使用malloc不止一个声明。
  3. 然后系统的地方到指针变量(p,在这种情况下)保留的地址块。指针变量本身包含一个地址。分配的块能够持有指定的值类型,指针指向它。

下检查指针p程序确保分配请求成功线如果(p = = 0)(可能也被写成如果(p = = NULL)甚至如果p (!)。如果分配失败(如果p = 0),程序终止。如果配置成功,程序初始化块价值5,输出值,调用自由函数返回内存堆前的程序终止。

真的没有区别这段代码和以前的代码集p等于现有的整数的地址我。唯一的区别是,在变量的情况下,我的记忆存在作为程序的预分配的内存空间的一部分,这两个名字:* p。从堆中分配的内存,这个街区有一个名字* p在程序的执行和分配。两个常见的问题:

  • 真的是重要的检查,每个分配后指针为零?是的。自堆大小变化不断根据哪些程序正在运行,他们分配多少内存,等等,没有任何保证调用malloc会成功。18新利最新登入您应该检查后的指针调用malloc确保指针是有效的。
  • 如果我忘记删除程序终止前一块内存吗?当程序终止时,操作系统“清理后,发布可执行代码空间,栈,全球回收和任何堆分配内存空间。因此,没有长期后果期间离开分配在程序终止。18新利最新登入然而,它被认为是不好的形式,“内存泄露”在程序执行的是有害的,我们将在下面进行讨论。

以下两个项目显示两种不同有效使用的指针,并试图区分使用指18新利最新登入针和指针的值:

void main () {int * p *问;p = (int *) malloc (sizeof (int));q = p;* p = 10;printf (" % d \ n”*问);* q = 20;printf (" % d \ n”*问);}

这段代码的最终输出将从4号线10和20从第6行。

下面的代码略有不同:

void main () {int * p *问;p = (int *) malloc (sizeof (int));q = (int *) malloc (sizeof (int));* p = 10;* q = 20;* p = *;printf (" % d \ n”* p);}
这段代码的最终输出将从4号线10和20从第6行。

最终的输出从这个代码将从第6行20。

最终的输出从这个代码将从第6行20。

注意,编译器将允许* p = * q,因为* p和q都是整数。这个声明说,“将整数值指着问到整数的值指出p。”该声明moves the values. The compiler will also allowp =,因为p和q都是指针,指向相同的类型(如果s是一个指向字符的指针,p =年代是不允许的,因为它们指向不同的类型)。该声明p =说,“点p同一块点。”In other words, the address pointed to by q is moved into p, so they both point to the same block. This statement moves the addresses.

从所有这些例子中,您可以看到,有四种不同的方法来初始化一个指针。当声明一个指针,在int * p程序中,它开始在未初始化的状态。它可能在任何地方,因此间接引用,这是一个错误。初始化一个指针变量在内存中包含指向到一个已知位置。

  1. 的一种方式,就像已经是使用malloc声明。这句话从堆中分配一块内存块的指针,然后点。这个初始化指针,因为现在点到一个已知位置。初始化指针,因为它已经装满了一个有效的地址,新的块的地址。
  2. 第二种方法,就像刚才,是使用一个语句等p =所以p点相同的地方。如果问指着一个有效的阻止,那么p是初始化。p是富含有效地址的指针q包含。18新利最新登入然而,如果q是未初始化的或无效的,p将无用的地址相同。
  3. 第三种方法是指针指向一个已知地址,如一个全局变量的地址。例如,如果我是一个整数,p是一个指向一个整数,然后声明p =我初始化p通过指向我。
  4. 第四个方法初始化指针使用价值为零。零使用指针是一个特殊的值,如下所示:p = 0;18新利最新登入或:p =零;什么这身体是将一个零放在p。指针p的地址是零。这通常是用图表表示出:

任何指针可以设置为零。当p点为零,然而,它并不指向一个街区。18新利最新登入只包含地址的指针零,这个值是有用的作为一个标记。你可以用它在语句如:

如果(p = = 0) {…}

或者:

而(p ! = 0) {…}

该系统还认识到零值,并将生成错误消息如果你碰巧零指针废弃。例如,下面的代码:

p = 0; * p = 5;

这个项目将会崩溃。p不指向一块的指针,它指向零,所以不能分配给* p值。零指针将被用作一个国旗当链表。

malloc命令用于分配一块内存。也可以释放的内存块时不再需要。当一块一致,它可以重用的后续malloc命令,它允许系统来回收内存。使用的命令来释放内存免费的,它接受一个指针作为参数。免费的命令都要做两件事:

  1. 指向的内存块的指针是无限制的,堆上的空闲内存。它可以重用后新的声明。
  2. 未初始化的指针离开状态,可以使用之前,必须初始化。

自由的声明只是返回一个指针指向其原始未初始化状态,使堆块再次可用。

下面的例子展示了如何使用堆。18新利最新登入它分配一个整数块,填充它,它写道,和处置:

# include < stdio。h > int main () {int * p;p = (int *) malloc (sizeof (int));* p = 10;printf (" % d \ n”* p);自由(p);返回0;}

这段代码是非常有用的只是为了展示分配的过程中,回收,使用一块在cmalloc行分配一块内存的大小指定——在这种情况下,sizeof (int)字节(4个字节)。的运算符用C命令返回的大小,以字节为单位,任何类型的。可以表示的代码malloc (4),因为sizeof (int)在大多数机器= 4字节。使用运算符然而18新利最新登入,使代码更加便携和可读的。

malloc函数返回的指针分配块。这个指针是通用的。使用指针没有铸字通常产生一个编译器的警告类型。的int (*)定型将通用malloc返回的指针转换成一个指针指向一个整数,“这是什么p预计。C中的自由语句返回一个块堆以便重用。

第二个例子展示了与前面的示例相同的功能,但它使用一个结构,而不是整数。在C语言中,代码是这样的:

# include < stdio。h > struct rec {int我;浮动f;字符c;};int main () {struct rec * p;p = (struct rec *) malloc (sizeof (struct rec));(* p)我= 10;(* p) .f = 3.14;(* p) . c = ' a '; printf("%d %f %c\n",(*p).i,(*p).f,(*p).c); free(p); return 0; }

注意以下行:

(* p)我= 10;

很多人想知道为什么不工作:

* p = 10;

答案c的优先级与运营商的结果计算5 + 3 * 4 = 17,不是32,因为*操作符的优先级高于+在大多数计算机语言。在C语言中,运算符的优先级高于*,所以括号力适当的优先级。

大多数人厌倦打字(* p)我所有的时间,所以C提供了一个简化符号。以下两个语句是完全等价的,但第二个更容易类型:

(* p)我= 10;p - > = 10;

你会看到第二个比第一个更经常在阅读别人的代码。

Baidu