存储类别和动态内存分配有何联系?我们来看一个理想化模型。可以认为程序把它可用的内存分为3部分:一部分供具有外部链接、内部链接和无链接的静态变量使用;一部分供自动变量使用;一部分供动态内存分配。
静态存储类别所用的内存数量在编译时确定,只要程序还在运行,就可以访问储存在该部分的数据。该类别的变量在程序开始执行时被创建,在程序结束时被销毁。
然而,自动存储类别的变量在程序进入变量定义所在块时存在,在程序离开块时消失。因此,随着程序调用函数和函数结束,自动变量所用的内存数量也相应地增加和减少。这部分的内存通常作为栈来处理,这意味着新创建的变量按顺序加入内存,然后以相反的顺序销毁。
动态分配的内存在调用malloc()或相关函数时存在,在调用free()后释放。这部分的内存由程序员管理,而不是一套规则。所以内存块可以在一个函数中创建,在另一个函数中销毁。正是因为这样,这部分的内存用于动态内存分配会支离破碎。也就是说,未使用的内存块分散在已使用的内存块之间。另外,使用动态内存通常比使用栈内存慢。
总而言之,程序把静态对象、自动对象和动态分配的对象存在不同的区域。
示例
//Visual Studio中加上这句才可以使用scanf() //否则只能使用scanf_s() #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <ctype.h> //malloc()、free() #include <stdlib.h> int static_store = 30; const char * pcg = "String Literal"; //argc: 参数个数 argv[]: 参数数组 //int main(int argc, char **argv) int main(int argc, char *argv[]) { int auto_store = 40; char auto_string[] = "Auto char Array"; int * pi; char * pcl; pi = (int *)malloc(sizeof(int)); *pi = 35; pcl = (char *)malloc(strlen("Dynamic String") + 1); strcpy(pcl, "Dynamic String"); printf("static_store: %d at %p\n", static_store, &static_store); printf(" auto_store: %d at %p\n", auto_store, &auto_store); printf(" *pi: %d at %p\n", *pi, pi); printf("%s at %p\n", pcg, pcg); printf("%s at %p\n", auto_string, auto_string); printf("%s at %p\n", pcl, pcl); printf("%s at %p\n", "Quoted String", "Quoted String"); free(pi); free(pcl); system("pause"); return 0; }
运行测试
如上所示,静态数据(包括字符串字面量)占用一个区域,自动数据占用一个区域,动态分配的数据占用第3个区域(通常被称为内存堆或自由内存)。