前面提到的存储类型,在确定了存储类别之后,会根据已制定好的内存管理规则,将自动选择其作用域和存储期,然而,还有更灵活的选择,即用库函数分配和管理内存。
所有程序都必须预留足够的内存来存储程序使用的数据,这些内存中有些是自动分配的,例如声明float x;
char place[] = "Dancing";
为一个float类型和一个字符串预留了足够的内存,或者可以显示指定分配一定数量的内存int plates[100];
,该声明预留了100个内存的位置,每个位置用于存储int类型的值。声明还为内存提供了一个标识符,因此,可以使用x或place识别数据。
1.malloc()函数
C能够在程序运行时分配更多的内存,主要工具是malloc()函数,该函数接受一个参数表示所需的内存字节数long *ptd = (long *)malloc(100 * sizeof(long));
。malloc函数会找到合适的空闲内存块,这些内存是匿名的,即不用标识符标识,malloc函数返回动态分配内存块的首字节地址,因此可以把该地址赋给一个指针变量,并使用指针访问这块内存。通常,malloc()要与free()配套使用。free函数的参数是之前malloc函数返回的地址,该函数释放之前malloc分配的内存。因此,动态分配内存的存储期从调用malloc分配内存到调用free释放内存为止。
使用malloc()函数,程序可以在运行时才确定数组大小。它把内存块的地址赋给指针ptd,然后便可以使用数组名的方式使用ptd;另外,如果内存分配失败,可以调用exit()函数结束程序,其原型在stdlib.h中。标准提供了两个返回值以保证在所有操作系统中都能正常工作:EXIT_FAILURE表示程序异常终止,EXIT_SUCCESS(相当于0)表示普通程序的结束。这两个值也被定义在stdlib.h中。
2.free()函数
静态内存的数量在编译时是固定的,在程序运行期间也不会改变。自动变量使用的内存数量在程序执行期间会自动增加或减少。但是动态分配的内存数量只会增加,除非使用free()进行释放。
所以,如果忘记使用free(),可能会导致内存泄漏,因为被malloc分配的内存,如果指向该块内存的指针变量被销毁,但是已分配的内存空间仍然存在,只是无法再访问这块内存,因此不能被重复使用。所以在实际情况中,可能在程序还未执行结束,就已经耗尽了所有内存,这类问题都称为内存泄漏。因此,要记住使用free函数避免这类问题的发生。一些操作系统在程序结束时会自动释放动态分配的内存,但是有些系统不会,为保险起见,请使用free函数,不要依赖操作系统来清理。
3.calloc()函数
calloc()函数和malloc函数类似,返回指向void的指针,如果分配内存失败,则返回空指针,这是ANSI C标准的一个新类型,该类型相当于一个”通用指针“,把指向void的指针赋给任意类型的指针完全不用考虑类型匹配的问题,但是建议使用强制类型转换,因为在C++中必须使用,所以使用强制类型转换,更容易把C程序转换为C++程序。
calloc函数用法是long *newmem = (long *)calloc(100, sizeof(long));
,calloc函数接受两个无符号整数作为参数(ANSI规定是size_t类型)。第一个参数是所需的存储单元数量,第二个参数是存储单元的大小,以字节为单位。calloc()函数还有一个特性:将块中所有位都设置为0,free函数也可用于释放calloc函数分配的内存。