C中的字符串文字数组是如何存储的?

How is array of string literal in C stored?

看看下面的代码和输出:

char *words[] = {"wehrmarcht", "collectorate", "hello", "hello","precorrection", "hello","wehrmarcht"};
char *wp;
cnode *np;
for(wp = *words; wp - *words < sizeof(words); wp += strlen(wp) + 1) {
    printf("wp -> %s\n", wp);
}
printf("==============================================\n");
for(int i = 0; i < sizeof(words) / sizeof(char *); i++) {
    printf("words[%d] -> %s\n", i,words[i]);
}

输出:

wp -> collectorate
wp -> precorrection
wp -> wp -> %s

wp -> ==============================================

==============================================
words[0] -> wehrmarcht
words[1] -> collectorate
words[2] -> hello
words[3] -> hello
words[4] -> precorrection
words[5] -> hello
words[6] -> wehrmarcht

Process finished with exit code 0

谁能解释一下是什么让 wp 指向代码中的某些字符串? 提前致谢。

为了实验,我把你的例子改成了 显示字符串的地址。
你可以看到我们不能对方式做任何假设 这些字符串中的每一个都相对于彼此存储。

在我的系统(Linux 64 位)上我得到:

$ ./prog_c
words[0] @ 0x5631c83b6080 -> wehrmarcht
words[1] @ 0x5631c83b60c0 -> collectorate
words[2] @ 0x5631c83b6100 -> hello
words[3] @ 0x5631c83b6100 -> hello
words[4] @ 0x5631c83b6140 -> precorrection
words[5] @ 0x5631c83b6100 -> hello
words[6] @ 0x5631c83b6080 -> wehrmarcht
/**
  gcc -std=c99 -o prog_c prog_c.c \
      -pedantic -Wall -Wextra -Wconversion \
      -Wc++-compat -Wwrite-strings -Wold-style-definition -Wvla \
      -g -O0 -UNDEBUG -fsanitize=address,undefined
**/

#include <stdio.h>

int
main(void)
{
  const char *words[]={"wehrmarcht", "collectorate", "hello", "hello", "precorrection", "hello", "wehrmarcht"};
  const int count=(int)(sizeof(words)/sizeof(words[0]));
  for(int i=0; i<count; ++i)
  {
    printf("words[%d] @ %p -> %s\n", i, (void *)words[i], words[i]);
  }
  return 0;
}

How is array of string literal in C stored?

我想你是误会了,数组words[]中的char指针所指向的字符串字面量是后续存储在内存中的,其实不然。只有 char 个指针存储在连续内存中。

此外,您似乎将 0x764f73a1 之类的内存地址与对象或数组的大小(以字节为单位)混合在一起。


因此,您的第一个 for 循环:

for(wp = *words; wp - *words < sizeof(words); wp += strlen(wp) + 1) {
    printf("wp -> %s\n", wp);
}

调用未定义的行为并且没有意义。

1.

wp = *words

wp 由第一个字符串文字的地址分配。

2.

 wp - *words < sizeof(words)

这个条件没有意义。您将指向 char words 的指针数组的大小与指针 wp 保存的地址作为值减去第一个字符串文字的地址进行比较。

3.

 wp += strlen(wp) + 1

这不起作用,因为字符串文字不必连续存储在内存中。


与此相反,第二个 for 循环:

for(int i = 0; i < sizeof(words) / sizeof(char *); i++) {
    printf("words[%d] -> %s\n", i,words[i]);
}

是正确的,因为它只使用数组 words 中的 char 指针,并且只迭代与 words.

中的指针一样多的次数