C++ 理解C字符串&;C+中的字符串文字+;

C++ 理解C字符串&;C+中的字符串文字+;,c++,arrays,string,string-literals,c-strings,C++,Arrays,String,String Literals,C Strings,我想问一些关于字符串文字和C字符串的问题 所以如果我有这样的东西: char cstr[] = "c-string"; char *cstr = alloca(strlen("c-string")+1); memcpy(cstr,"c-string",strlen("c-string")+1); 据我所知,字符串文本是在内存中创建的,带有一个终止的空字节,例如,从地址0xA0开始,到0xA9结束,然后从那里返回和/或转换为char[]类型,然后指向地址 因此,执行以下操作是合法的: for

我想问一些关于字符串文字和C字符串的问题

所以如果我有这样的东西:

char cstr[] = "c-string";
char *cstr = alloca(strlen("c-string")+1);
memcpy(cstr,"c-string",strlen("c-string")+1);
据我所知,字符串文本是在内存中创建的,带有一个终止的空字节,例如,从地址0xA0开始,到0xA9结束,然后从那里返回和/或转换为char[]类型,然后指向地址

因此,执行以下操作是合法的:

for (int i = 0; i < (sizeof(array)/sizeof(char)); ++i)
    cstr[i] = 97+i;
我想我想理解的是为什么char*类型不能像数组那样指向字符串文本并修改它们的常量?为什么字符串文本不像对char[]那样被强制转换成char*?如果我在这里有错误的想法或者我完全不在,请随时纠正我。

char cstr[]=“某物”正在声明一个自动数组初始化为字节“s”、“o”、“m”

char*cstr=“某物”声明一个字符指针,该指针初始化为文本“something”的地址

这会将“c字符串”复制到堆栈上的字符数组中。写入此内存是合法的

char * p = "const cstring";
*p = 'A'; // illegal memory write
像“c-string”和“const-cstring”这样的文本字符串存在于二进制文件的数据段中。此区域是只读的。上面的p指向该区域中的内存,写入该位置是非法的。由于C++11比以前更严格地执行了这一点,因此必须改为
const char*p


相关问题。

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

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

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


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

您缺少的是一个小小的编译器魔法,其中:

char cstr[] = "c-string"; 
实际上是这样执行的:

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

您看不到该位,但它或多或少是代码编译的结果。

char*p=“const cstring”
应该抛出一个编译错误,因为
“const cstring”
是类型
const char*
(具体地说,这样您就不会像在示例中那样使用它)@tylerl
“const cstring”
不是类型
const char*
@LightnessRacesinOrbit是类型
const char[N]
,这可能相当于
常量字符*
。你可以争辩那些迂腐的细节,但那只会增加混乱,而不是清晰。@tylerl相反,这些是完全不同的类型,假装不这样是混乱的导火索。啊,我明白了。所以区别在于,一个实际上只是指向RO内存的指针,而另一个是指向内存中该文本的本地副本加上空字节的char数组变量(换句话说是常量指针),因此对副本的访问是RW。顺便说一句,感谢你澄清了过去并不总是RO内存。在开始将字符串放入只读部分之前,修改“常量”字符串是C程序员的老把戏。这绝对是我一直缺少的!我选择的答案基本上是用文字表达的,但代码更简洁;)因此,cstr实际上是堆栈(或堆)上本地分配内存的const char*,它是一个副本,可修改,与文本字符串的值不同。非常感谢您给我看这个。值得指出的是,在这种情况下,
cstr
不是
const char*
,而是
char*
const char*
是字符串文本的结果。这意味着你不能修改它的内容。相反,
char*
表示数据是可修改的。而且,它肯定在堆栈上,而不是堆上,这就是为什么您不必对它调用
free()
,也不能
将它返回给调用方的原因。感谢您对这方面的深入了解。我现在看到,数组作为一种标准类型,实际上是在构造函数中由字符串文本初始化的,但只是文本本身的副本。