3

我有几个关于字符串文字和 C 字符串的问题。

所以,如果我有这样的事情:

char cstr[] = "c-string";

据我了解,字符串文字是在内存中创建的,带有一个终止空字节,例如从地址 0xA0 开始并在 0xA9 结束,然后从那里返回地址和/或转换为类型 char [ ] 然后指向地址。

然后执行此操作是合法的:

for (int i = 0; i < (sizeof(array)/sizeof(char)); ++i)
    cstr[i] = 97+i;

所以从这个意义上说,只要将字符串文字转换为 char [ ] 类型,就可以修改它们吗?

但是对于常规指针,我开始明白,当它们指向内存中的字符串文字时,它们无法修改内容,因为大多数编译器在常量的某个下限地址空间中将分配的内存标记为“只读”。

char * p = "const cstring";
*p = 'A'; // illegal memory write

我想我想了解的是为什么不允许 char * 类型像数组一样指向字符串文字并修改它们的常量?为什么字符串文字不像 char [ ] 那样被转换为 char *?如果我在这里有错误的想法或完全不正确,请随时纠正我。

4

4 回答 4

4

您缺少的一点是一点编译器魔术,其中:

char cstr[] = "c-string"; 

实际上是这样执行的:

char *cstr = alloca(strlen("c-string")+1);
memcpy(cstr,"c-string",strlen("c-string")+1);

你看不到那一点,但它或多或少是代码编译成的。

于 2011-10-06T03:41:19.987 回答
2

char cstr[] = "something";正在声明一个初始化为字节's','o','m',...的自动数组

char * cstr = "something";另一方面,声明一个字符指针初始化为文字“某物”的地址

于 2011-10-06T03:36:28.040 回答
1
char cstr[] = "c-string";

这会将“c-string”复制到堆栈上的 char 数组中。写入该内存是合法的。

char * p = "const cstring";
*p = 'A'; // illegal memory write

像“c-string”和“const cstring”这样的文字字符串存在于二进制文件的数据段中。该区域是只读的。以上 p 指向该区域的内存,写入该位置是非法的。由于 C++11 比以前更严格地执行此操作,因此您必须const char* p改为执行此操作。

相关问题在这里

于 2011-10-06T03:37:18.103 回答
1

在第一种情况下,您正在创建一个实际的字符数组,其大小取决于您初始化它的文字的大小(8+1 个字节)。该cstr变量在堆栈上分配了内存,字符串文字的内容(在代码中位于其他地方,可能在内存的只读部分中)被复制到该变量中。

在第二种情况下,局部变量p也在堆栈上分配了内存,但它的内容将是您初始化它的字符串文字的地址。

因此,由于字符串文字可能位于只读内存中,因此尝试通过p指针更改它通常是不安全的(您可能会相处,也可能不会)。另一方面,您可以对cstr数组做任何事情,因为这是您的本地副本,恰好是从文字初始化的。

(请注意:cstr变量是char 类型的数组,在大多数情况下,这将转换为指向该数组的第一个元素的指针。例外情况可能是sizeof运算符:这个计算整个数组的大小,不仅仅是指向第一个元素的指针。)

于 2011-10-06T03:38:12.453 回答