C 中存储的指针和全局变量在哪里?它们是保存在内存,堆还是堆栈中?
答案 0 :(得分:25)
全局变量可以在几个地方,具体取决于它们的设置方式 - 例如,const
全局变量可能位于可执行文件的只读部分。 “Normal”全局变量位于可执行文件的读写部分。它们根本不在堆或堆栈上。指针只是一种变量,因此它们可以位于您希望它们的任何位置(如果您malloc()
则在堆上;如果它们是局部变量则位于堆栈上;如果它们是局部变量,则位于数据部分中全局)。
答案 1 :(得分:8)
编译文件时,在“编译单元”(粗略地称为“c文件”)中定义的具有“程序持续时间”(静态或全局变量)的变量决定了该程序需要多少全局空间,以及如何初始化。
当链接器创建可执行文件时,它会将此信息组合在一起,并将其放入用于此目的的可执行文件的各个部分中。然后,链接器会通过并将对该数据的所有引用更改为在加载程序时将该数据放入进程的内存空间的位置。所以全局数据的指针就像源文件中的常量一样;不需要为他们留出任何记忆。
对于零初始化或未初始化的全局数据,仅存储此类数据所需的空间量。对于初始化数据,存储初始值。
当你的程序被加载时,加载器将查看程序文件以告知零初始化数据需要多少,并为其预留足够的进程内存空间,并将其全部初始化为二进制零。对于初始化数据,它为此留出内存并将其初始化为exe文件中保存的初始值。它还为堆(由malloc()使用)和堆栈预留了区域。
如果您的代码位于动态库中,则链接器无法知道它将放置全局数据的位置。在这种情况下,它在库中创建部分以告诉它对全局数据的引用的位置,并且加载器负责在加载文件时将引用更改为指向正确的位置(这就是为什么你在dcc的gcc命令行上传递-fPIC的原因。但由于这是在加载时完成的,所以当程序运行时,数据的放置是已知的,因此加载器知道数据指向全局数据的指针仍然可以作为程序中的常量。
如果动态链接到dll,加载器不知道它,所以你必须调用知道如何加载dll并获取其导出数据和函数地址的函数。
答案 2 :(得分:6)
全局变量通常存储在应用程序的数据段中。
指针的存储方式与其他变量的存储方式不同(例如,如果您有一个int*
类型的局部变量,它将存储在堆栈中,与任何其他局部变量相同。)
答案 3 :(得分:4)
malloc(),calloc()或realloc()所做的所有分配都存储在堆上,而所有局部变量都存储在堆栈中。
所有全局变量和静态变量都存储在数据段中,而常量存储在代码段中。
答案 4 :(得分:-2)
来自malloc()
的内存来自堆。这提供了指向内存的指针。
更多信息here。