我想问一些关于字符串文字和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 *?如果我在这里有错误的想法或完全关闭,请随时纠正我。
答案 0 :(得分:4)
你缺少的是一个小编译器魔术:
char cstr[] = "c-string";
实际执行如下:
char *cstr = alloca(strlen("c-string")+1);
memcpy(cstr,"c-string",strlen("c-string")+1);
你没有看到这一点,但它或多或少是代码编译的内容。
答案 1 :(得分:2)
char cstr[] = "something";
声明自动数组 已初始化 到字节'','o','m',......
char * cstr = "something";
声明一个字符指针初始化为文字“某事物”的 地址 。
答案 2 :(得分: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
。
相关问题here。
答案 3 :(得分:1)
在第一种情况下,您要创建一个实际的字符数组,其大小由您使用(8 + 1字节)初始化它的文字大小决定。 cstr
变量在堆栈上分配内存,字符串文字的内容(在代码中位于其他地方,可能在内存的只读部分)是复制到这个变量。
在第二种情况下,局部变量p
也在堆栈上分配了内存,但其内容将是您正在初始化它的字符串文字的地址。 / p>
因此,由于字符串文字可能位于只读存储器中,因此尝试通过p
指针进行更改通常是不安全的(您可能会相处,或者您可能不会) 。另一方面,您可以对cstr
数组执行任何操作,因为这是您刚才从文字初始化的本地副本。
(只需注意一点:cstr
变量属于类型的char ,在大多数情况下,这会转换为指向该数组第一个元素的指针。对此的例外可能是例如sizeof
运算符:这个运算符计算整个数组的大小,而不仅仅是指向第一个元素的指针。)