C字符串不可变?
根据我的理解,两行代码都创建了6个元素的字符串:
char * output = "AAAAAA" ; char * output [6] ;
那么,当我试图改变第一个数组字节时,为什么cprogramm在第一个分配情况下崩溃了。 为什么不在第二种情况下崩溃?
* output = 49; printf("%s\n",output);
你的理解是错误的。
第一行创建一个指向char的指针,该指针指向字符串“AAAAAA”,该字符串通常存储在可执行文件的不可变数据部分中。 您可以使用非const指针指向它的事实是一个令人遗憾的向后兼容遗留问题。 这就是崩溃的原因。 你应该写:
const char* output = "AAAAAA";
顺便说一句,字符数组有7个元素:’A’的6倍和终结符。
第二行根本不能做你想要的。 它是一个由6个指针组成的数组,使用代码甚至无法编译。 你可能意味着
char output[6];
这是一个由6个字符组成的数组,因此为长度为5的字符串提供空间(仍需要终结符的空间)。 无论如何,这个数组是可变的,所以你可以改变它的元素。
第一个只是一个指针,它被初始化为一个包含你的字符串的不可修改的内存。
第二个是初始化相同数据的数组。
你不能改变指针从第一行指向的数据,但你的数组当然是完全读/写的,就像任何非const
数组一样。
将字符串文字视为具有const char *
类型。
没有
char * output [6];
创建一个包含六个指向char
指针的数组。 即使你使用
char output [6];
你可能意味着什么,这不是一个字符串,而只是一个字符数组。 要使字符数组成为字符串,您必须遵守约定,以确保其中一个字符为0
。
由于您没有初始化arrays,因此没有这样的保证。
现在,对于您的第一种情况,这实际上不会“创建”新字符串,而是指向字符串文字。 字符串文字实际上不是可变的,并且clang拥有崩溃的所有权利。
第一种情况应该写成const char * output = "AAAAAA" ;
。 编译器在程序的只读部分创建字符串常量,并在其中指向output
。 您可以自由更改output
点的位置,但不能随意更改应用程序的只读部分的内容。
C-String数组初始化 – 这是可变的吗?
第一个创建指向字符串文字“hello”的指针,该指针可能存储在程序的可执行映像中的不可写存储器中。 即使不是,也不允许修改该数组的内容。
char*
和char[]
不是一回事。
以下是该标准的含义:
32年6月6日
arrays的内容是可修改的。 另一方面,声明char * p =“abc”; 使用类型”指向char’的指针定义p并初始化它以指向一个类型为”char’数组的对象,其长度为4,其元素用字符串文字初始化。 如果尝试使用p修改数组的内容,则行为未定义。
修改字符串文字的元素会导致未定义的行为“6.4.5字符串文字[#6]”。
PS。 我认为字符串文字被称为只读,这不是C标准中的要求,尽管它在C实现中很常见。 另一个考虑因素是,表示相同字符序列的不同(如lexemes)字符串文字可以对应于单个静态存储持续时间数组。
因为第一个’char * output =“AAAAA”;’ 将输出声明为指向包含字符AAAAA的只读存储区的指针。
然后尝试修改它的第一个字节,这可能是未定义的行为。