Pointers on C——11 Dynamic Memory Allocation.1

The elements of an array are stored in contiguous locations in memory. When an array is declared, its memory is allocated at compile time. However, you can also allocate the memory at runtime with dynamic memory allocation. In this chapter, we will examine the differences between these techniques and see when and how to use dynamic memory allocation.

数组的元素存储于内存中连续的位置上。当一个数组被声明时,它所需要的内存在编译时就被分配。但是,你也可以使用动态内存分配在运行时为它分配内存。在本章中,我们将研究这两种技巧的区别,看看什么时候我们应该使用动态内存分配以及怎样进行动态内存分配。


11.1 Why Use Dynamic Allocation

When declaring arrays, the array size must be given as a compile‐time constant. Often,the actual size needed for the array is not known until run time because the amount of space depends upon the input data. For example, a program that computes student grades and averages might need to store data for all of the students in a class, but different classes will have different numbers of students. In these situations, the usual approach is to declare an array that is as big as it ever will need to be.

当你声明数组时,你必须用一个编译时常量指定数组的长度。但是,数组的长度常常在运行时才知道,这是由于它所需要的内存空间取决于输入数据。例如,一个用于计算学生等级和平均分的程序可能需要存储一个班级所有学生的数据,但不同班级的学生数量可能不同。在这些情况下,我们通常采取的方法是声明一个较大的数组,它可以容纳可能出现的最多元素。


This approach has the advantage of being simple, but it has several disadvantages.First, such declarations build an artificial limitation into the program, making it incapable of handling problems larger than the size used in the declaration. The obvious solution is to make the array even bigger, but the second problem then becomes even worse. Nearly all of the memory used for a huge array is wasted when the number of elements actually required is small. A third disadvantage is that the program must respond in a reasonable way when there is more input than the array can hold. It should not fail with an exception, and it must not print answers that look valid but in fact are wrong. The required logic is simple enough, but the assumption that ʺthe array will never overflowʺ makes it very tempting to not bother implementing it.

这种方法的优点是简单,但它有好几个缺点。首先,这种声明在程序中引入了人为的限制,如果程序需要使用的元素数量超过了声明的长度,它就无法处理这种情况。要避免这种情况,显而易见的方法是把数纽声明得更大一些,但这种做法使它的第2 个缺点进一步恶化。如果程序实际需要的元素数量比较少时,巨型数组的绝大部分内存空间都被浪费了。这种方法的第3 个缺点是如果输入的数据超过了数组的容纳范围时,程序必须以一种合理的方式作出响应。它不应该由于一个异常而失败,但也不应该打印出看上去正确实际上却是错误的结果。实现这一点所需要的逻辑其实很简单,但人们在头脑中很容易形成"数组永远不会溢出"这个概念,这就诱使他们不去实现这种方法。


11.2 Malloc and Free

The C library provides two functions, malloc and free, that perform dynamic memory allocation and deallocation. These functions maintain a pool of available memory.

C 函数库提供了两个函数, malloc 和free ,分别用于执行动态内存分配和释放。这些函数维护一个可用内存池。


When a program needs additional memory, it calls malloc, which takes an appropriate piece of memory from the pool and returns a pointer to this block of memory to the program. The memory is not initialized in any way. If it is important that the memory be initialized, you must either do it yourself or use the calloc function (described in the next section). When a previously allocated piece of memory is no longer needed,free is called to return it to the pool for later reuse.

当一个程序另外需要一些内存时,它就调用malloc 函数, malloc 从内存池中提取一块合适的内存,并向该程序返回一个指向这块内存的指针。这块内存此时并没有以任何方式进行初始化。如果对这块内存进行初始化非常重要,你要么自己动手对它进行初始化,要么使用calloc函数(在下 一节描述)。当一块以前分配的内存不再使用时,程序调用free 函数把它归还给内存池供以后之需。


The prototypes for these two functions are shown below, and are in stdlib.h.

这两个函数的原型如下所示,它们都在头文件stdlib.h 中声明。


void *malloc( size_t size );

void free( void *pointer );


The argument to malloc is the number of bytes (characters) of memory that are needed. If the desired amount of memory is available, malloc returns a pointer to the beginning of the allocated block.

malloc 的参数就是需要分配的内存字节(字符)数。如果内存池中的可用内存可以满足这个需求, malloc 就返回一个指向被分配的内存块起始位置的指针。


malloc allocates contiguous blocks of memory. For example, a request for 100 bytes will be satisfied with 100 adjacent bytes, never with two or more separate chunks of memory. Also, malloc may actually allocate a chunk of memory slightly larger than requested. However, this behavior is implementation dependent, so you should not count on getting more memory than you requested.

malloc 所分配的是一块连续的内存。例如,如果请求它分配100 个字节的内存,那么它实际分配的内存就是100 个连续的字节,并不会分开位于两块或多块不同的内存。同时, malloc 实际分配的内存有可能比你请求的稍微多一点。但是,这个行为是由编译器定义的,所以你不能指望它肯定会分配比你的请求更多的内存。


What if the pool of memory is empty, or it does not contain a big enough block?In this case, malloc calls the operating system to obtain more memory and begins allocating pieces from this new chunk. If the operating system is unable to give more memory to malloc, then a NULL pointer is returned. Thus it is vital that the pointer returned by every call to malloc be checked to ensure that it is not NULL.

如果内存池是空的,或者它的可用内存无法满足你的请求,会发生什么情况呢?在这种情况下,malloc 函数向操作系统请求,要求得到更多的内存,并在这块新内存上执行分配任务。如果操作系统无法向malloc 提供更多的内存, malloc 就返回一个NULL 指针。因此,对每个从malloc 返回的指针都进行检查,确保它并非NULL 是非常重要的。


The argument to free must either be NULL or a value that was previously returned from malloc, calloc, or realloc (described below). Passing a NULL argument to free has no effect.

free 的参数必须要么是NULL.要么是一个先前从malloc 、calloc 或realloc (稍后描述)返回的值。向free 传递一个NULL 参数不会产生任何效果。


How does malloc know whether you want to store integers, floating‐point values, structures, or arrays in the memory youʹve requested? It doesnʹt—malloc returns a pointer of type void * for precisely this reason. The Standard states that a void * pointer can be converted to any other pointer type. Some compiler though,especially older ones, may require you to use a cast for the conversion.

malloc 又是如何知道你所请求的内存需要存储的是整数、浮点值、结构还是数组呢?它并不知情——malloc 返回一个类型为void *的指针,正是缘于这个原因。标准表示一个void *类型的指针可以转换为其他任何类型的指针。但是,有些编译器,尤其是那些老式的编译器,可能要求你在转换时使用强制类型转换。


On machines with boundary alignment requirements, the memory returned by malloc will always begin on a boundary that is suitable for the data type with the most stringent alignment requirements.

对于要求边界对齐的机器, malloc 所返回的内存的起始位置将始终能够满足对边界对齐要求最严格的类型的要求。

上一章 Pointers on C——10 Structures and Unions.16

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值