字符数组指针的数组

9
我对以下代码行感到困惑:
char* words[] = { "aaa", "bbbb", "ccccc", "dddddd" };

我理解的方式是,每个单词首先被存储,然后数组words的每个位置将指向每个单词的第一个字符。这些字符串是如何存储的?这里是否进行了动态分配,还是这些单词存储在栈上?
如果它们存储在栈上,它们是以哪种方式存储的?例如,如果我像下面这样打印words的一些内容:
#include <stdio.h>
int main () {
    char* words[] = { "aaa", "bbbb", "ccccc", "dddddd" };
    printf("\n\n(*words)[0] = %s", words[0]);
    printf("\n\n(*words)[0]+1 = %s", words[0]+1);
    return 0;
}

我本来想打印aaabbbb,但是我得到的是aaaaa。我不太明白这个原因,因为在我的理解中,words[0]+1应该指向字符串bbbb而非aaa的第二个字符。请问这里发生了什么事情?


你是否对 words[0] + 1(words + 1)[0]words[1] 感到困惑? - Kerrek SB
8个回答

15

这就像是..

在此输入图像描述

因为words是一个字符指针数组,所以每个words数组的索引都将保存字符串字面值的地址,即字符串字面值的基地址。如果您打印

 printf("%s",words[0])// index 0 will print aaa.

6
差别在于words[0]+1不同于words[0+1]
前者指向words[0]中的第二个字符,而后者指向第二个单词。

3

words[0]指向"aaa"中的第一个'a'。

words[0]+1将该指针向前移动一个字符,因此它指向第二个'a'。

words[1]指向"bbbb"。

words[1]+1指向"bbbb"中的第二个'b'。


2
依我看,words[0]+1 应该指向字符串 "bbbb" 而不是 "aaa" 的第二个字符。
不对。 words[0] 本身就是一个字符指针——通过将其加一,可以完全得到 "aaa" 的第二个字符。你想要的是 words + 1 或者 &words[0] + 1,这样才能正确地得到 "bbbb"。
此外,这些字符串本身是在启动可执行文件时分配的,它们可能被链接器放置在二进制文件的数据或 bss 部分。当你声明和初始化 words 时,它将像任何其他自动数组一样在堆栈上分配,并且它的项将被分配为指向每个字符串常量开头的指针。

我明白了。实际上,我尝试过像 words[1][1] = 'u' 这样的操作,来将 bbbb 改成 bubb,但是修改后 bbbb 仍然保持不变。这是因为字符串是只读的(我假设它们是 rvalues),所以是这样吗? - user1607425
@curvature 是的,它们是不可变的。庆幸它没有崩溃 - 修改字符串常量是未定义行为。 - user529758

1

字面字符串存储在静态内存中。它们的实际位置取决于实现,但字面字符串通常存储在可执行文件的数据部分中 - 这既不是动态分配也不是堆栈分配。然后,您的数组包含指向这些位置的指针。

words [0] +1 应该指向字符串 bbbb 而不是 aaa 的第二个字符。

这只是数组索引的工作方式。您使用 words [0] 索引字符串数组,现在您有一个字符串,并且任何操作都适用于该字符串。您不能在下标之外的数组索引处进行算术运算。要访问字符串 "bbbb",您应该使用 words [1]


1

堆栈空间都是动态分配的,也就是说它们在运行时分配。你编译的代码是否在堆或栈上动态分配?显然不是。常量的存储方式类似于代码的存储方式……它们存储在磁盘上的可执行文件中,并加载到只读内存中。(注:这是典型实现的做法,而非语言标准规定的做法。)

words[0] 是 "aaaa" 中第一个 'a' 的地址。将该地址加 1,应该得到 "aaaa" 中第二个 'a' 的地址。"bbbb" 的地址在 words[1] 处。

在你的 printf 格式中,你有 "(*words)[0]",但那是不同的。 *wordswords[0] 是相同的。 (*words)[0]**words 是 "aaaa" 中第一个 'a'(而不是它的地址)。你应该用 %c 而不是 %s 打印 (*words)[0]


0
char* words[] = { "aaa", "bbbb", "ccccc", "dddddd" };

所有4个字符串都具有静态存储期,并在程序启动之前分配。
在初始化器中,数组被转换为指向char的指针,并使用指针值初始化words数组。

0

words[0] 返回 aaa 的地址。将其加1会将地址增加到指向第二个 a。

你的意思是要使用 words[0+1] 吗?

那应该会得到你期望的结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接