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
.
中的指针一样多的次数
看看下面的代码和输出:
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
.