2011-08-16 67 views
6

这是一个基于答案由提问一个问题:字符数组VS字符*

const char myVar* vs. const char myVar[]

const char* x = "Hello World!"; 
const char x[] = "Hello World!"; 

我现在理解上的差异,但我的新问题是:

(1)什么发生在第一行的“Hello World”字符串,如果我重新分配x?没有什么会指出这一点 - 当范围结束后它会被销毁吗?

(2)除了常量外,这两个示例中的值如何在编译器中不同地存储在内存中?

回答

9

在您的代码中放置"Hello World!"会导致编译器将该字符串包含在编译的可执行文件中。在执行程序之前,在调用main之前在内存中创建字符串,我相信甚至在程序集调用__start(这是静态初始化程序开始运行时)之前。 char * x的内容未使用newmalloc分配,或者在main的堆栈帧中分配,因此不能分配。

但是,在函数或方法中声明的char x[20] = "Hello World"在堆栈中分配,而在范围内,实际上在内存中将有两个"Hello World"副本 - 一个预加载可执行文件,一个在堆栈中 - 分配缓冲区。

+0

const char x []应该将数据复制到堆栈。 –

-1
  1. 形式上在两种情况下,"Hello World!"字符串在静态存储器作为char的连续序列分配的,所以不存在动态分配的内存以回收或任何类的实例来破坏;
  2. 这两个x将被分配在静态存储器或堆栈中,具体取决于它们的定义。但是,指针将被初始化以指向相应的"Hello World!"字符串,而数组将通过将字符串直接复制到其中而被初始化。

理论上,编译器可以在没有办法访问它们时自由地回收这两个字符串文本的内存;在实践中,第一个不太可能被回收,因为通常静态内存仍然被分配给程序直到其终止;另一方面,如果数组在堆栈上分配,第二个数据甚至可能根本就不被分配,因为编译器可能使用其他方法来确保数组已正确初始化,并且数组内存将在其退出时被回收范围。

+0

除此之外,用指针做sizeof(x)将导致4(或64位代码中的8),而带数组的sizeof(x)将导致数组包含的字节数。 – Matthew

+2

-1:它们不以相同的方式分配。第一个例子是一个指向静态内存的指针。第二个例子是一个非静态数组,其内容用'“Hello world!”'初始化。 –

+2

我认为const char x []背后的想法是数组在堆栈上,而不仅仅是一个指针,并且“Hello World!”被复制到它。这可能会被优化,但这个想法与简单的指针完全不同。 –

4

编译器将第一个存储在名为RODATA(只读数据)的内存部分中。只要程序仍在运行,内存仍然保持其初始值。

第二个存储就像任何其他数组 - 在堆栈上。就像任何其他局部变量一样,一旦范围结束,它就可能被覆盖。

+0

'只要程序仍在运行,内存仍然保持其初始值。'也就是说,字符串的范围是程序范围,而不是函数的范围。 –