存储在内存中的字符指针数组在哪里?

时间:2012-02-27 20:04:36

标签: c

所以,如果我这样做:

char * a = "hello";

“hello”存储在RODATA部分中并指向它。如果我这样做:

char a[10] = "hello";

“hello”以10个字节的数组存储在STACK中,称为。

当我这样做时会发生什么:

char * a[10] = {"hello", "hi"}

因此,我们有一个包含10个字符指针的数组,这些指针将存储在STACK中。但是字符串文字怎么样?他们是否进入RODATA部分?
另外,argv会发生同样的事情吗?

6 个答案:

答案 0 :(得分:4)

char *a[10] = {"hello", "hi"}

数组的元素是指向字符串文字的指针。作为任何字符串文字,它们也是不可修改的,并且实现可以将它们存储在只读存储器中。

*a[0] = 'g';   // undefined behavior, modifying a string literal
a[0] = "bla";  // ok, modifying the pointer

现在提出第二个问题:

  

此外,argv也会发生同样的事情吗?

不,因为它们不是字符串文字。可以修改argv中的指针和指向的字符串。这是由C标准保证的。

  

(C99,5.1.2.2.1p2)“参数argc和argv以及argv数组指向的字符串应该可由程序修改,并在程序启动和程序终止之间保留它们最后存储的值。” / p>

答案 1 :(得分:3)

嗯,正在浏览gcc -S

cnicutar@cvm:~$ head try.S 
    .file   "try.c"
    .text
.Ltext0:
    .section    .rodata
.LC0:
    .string "hello"
.LC1:
    .string "hi"

或者,从二进制文件:

cnicutar@cvm:~$ objdump -s -j .rodata try

try:     file format elf32-i386

Contents of section .rodata:
 80484e8 03000000 01000200 68656c6c 6f006869  ........hello.hi
 80484f8 00                                   .               

这是该计划:

int main()
{
    char * a[10] = {"hello", "hi"};
    (void)a;
    return 0;
}

答案 2 :(得分:2)

您的第一个假设可能适用于您的情况,但在其他平台和编译器上并不一定如此。但就你的问题而言,让我们假设它是。

你的第二个假设是不正确的。 "hello"存储在与第一种情况相同的位置。只是它的字符(和尾随的0)被复制到堆栈中的a(就C而言,它也不是一个明确定义的术语)。

在你的第三个例子中

char * a[10] = {"hello", "hi"}

"Hello""hi"存储在第一个示例中的任何位置,例如RODATA。第一个字符的指针存储为a的前两个元素

答案 3 :(得分:1)

char * a[10] = {"hello", "hi"}
  

所以,我们有一个10个字符的数组

这不正确。我们有10个(本地)指向chars(或char数组)的指针。 “hello”和“hi”将像第一个例子一样存储在数据部分中。

答案 4 :(得分:1)

在第三种情况下,你有一个10个指针的数组,它使用10 * sizeof(char*)个字节的内存。前两个元素指向数据段中相应的常量字符串。

答案 5 :(得分:1)

String literals: Where do they go?

进行了长时间的讨论

它们将在某个地方,具有静态存储持续时间。除此之外,它将取决于您的编译器。

你将拥有,例如(在一个带有1个字节指针的机器上,因为我很懒)

RODATA:
0x00:    hello0
0x06:    hi0

Stack:
0xA0: 0x00
0xA1: 0x06
0xA2: 0x00
[...]