假设我写了一个函数如下:
void foo()
{
char *strArr[] = {"AA", "BB", "CC"};
...
}
strArr 将分配到哪里?什么时候初始化?
出于某种原因,我记得这样一个数组将分配在静态内存空间中,而不是在堆栈上并在程序启动时初始化,就好像我会在它之前写“静态”一样。难道是假记忆?
假设我写了一个函数如下:
void foo()
{
char *strArr[] = {"AA", "BB", "CC"};
...
}
strArr 将分配到哪里?什么时候初始化?
出于某种原因,我记得这样一个数组将分配在静态内存空间中,而不是在堆栈上并在程序启动时初始化,就好像我会在它之前写“静态”一样。难道是假记忆?
它具有自动存储功能,因此它将被分配到函数的堆栈上。元素属于这种自动存储,但字符串文字本身存储在一个持久的、可能是只读的区域中。
该数组将作为本地对象分配。在一般情况下,所有本地对象的内存可以在函数开始执行时尽早分配,或者可以“按需”分配,因为控制进入带有对象声明的嵌套块。该语言没有指定确切的时刻。
在您的具体示例中,将在函数开始执行时分配数组的内存,因为您的数组是在函数的“主”块中声明的。
至于初始化……在 C89/90 版本的 C 中,所有聚合初始化器都必须是常量表达式,这意味着聚合初始化过程不能依赖于任何运行时值。初始化可以硬编码到已编译的程序中,并且可以在分配数组后立即进行。
在 C99 中,您可以在聚合初始值设定项中使用运行时值,这意味着实际初始化可能必须延迟到控制传递声明时的时间点。
在您的示例中,数组是用常量表达式初始化的,这意味着它可以在分配后立即初始化。编译器实际上可以提前准备数组的静态副本,并在每次控件进入函数时简单地将其“粘贴”到堆栈中。
PS您对“静态内存”的引用实际上适用于"AA"
用于初始化数组元素的字符串文字(如 )。字符串文字确实驻留在静态内存中。但是,字符串文字是完全独立的对象,而您的strArr
数组是完全独立的对象。
请注意,您的示例中并没有真正的“字符串数组”。你所拥有的是一个指向字符串的指针数组。您strArr
生活在本地内存中,而字符串(指向哪些元素strArr
)则生活在静态内存中。
我只是反汇编了一个示例程序。
#include <stdio.h>
void foo()
{
char *strArr[] = {"AA", "BB", "CC"};
}
int main()
{
foo();
return 0;
}
看来,字符串文字将在.rodata
部分中分配。
.file "sfsfs.c"
.section .rodata
.LC0:
.string "AA"
.LC1:
.string "BB"
.LC2:
.string "CC"
.text
.globl foo
.type foo, @function
foo:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
.....
.....
但是 strArr 将仅在堆栈中分配。因为它是自动的。