在C语言中,char *s和char s[]的区别是否适用于其他类型?

3

I have seen (1, 2) that:

char s[] = "abc";
char t[3] = "abc";

实际上是完全相同的:

char s[] = { 'a', 'b', 'c', '\0' };
char t[] = { 'a', 'b', 'c' };

以下内容如下:

char *word = "abc";
word[0] = 'd';

word放入只读内存中,导致非法的内存操作word[0] = 'd' 出错。

这仅针对char类型吗?当我执行类似以下内容时,没有出错:

int array[] = {1, 2, 3};
int *p = array;
p[0] = 0; // No error here
array[1] = 1; // or here

2
是的,这些行为是特定于字符数组和字符串字面值的。请阅读C标准以获取完整细节。 - kaylum
2
真的不知道为什么他们要对你的问题进行投反对票。 - UrbiJr
1
在你的第一段代码中,t[3] = "abc" 应该是 char t[3] = "abc"; 同样地,在你的第二段代码中也是如此。 - Keith Thompson
2
第一行和第二行并不相同。标准中也没有对ROM的要求。运行操作系统的PC甚至没有ROM。也没有生成运行时错误的要求。你的意图或实际问题并不清楚。这些片段甚至不能进行比较,还有信息缺失。 - too honest for this site
1
请注意,word本身是一个可修改的变量;它可以被赋予一个新的指针值。当你使用char *word = "abc";时,你让它指向一个字符字面量,这被视为一个字符数组。试图修改一个字符串字面量会导致未定义的行为。该字符串不一定在只读内存中(尽管现在通常是这样)。尝试将"abc"修改为"dbc"可能会成功,并且可能同时修改一个字符串字面量"xyzabc""xyzdbc" - 或者可能失败并导致程序崩溃。你应该使用const char *word = "abc"; - Jonathan Leffler
嗨,Jonathan,你说 char *word = "abc"; 使 word "指向一个字符文字,被视为一个字符数组。" 然而,字符数组很容易被修改。使用以上代码,我可以毫无问题地说 s[0] = 'b'。你能否请澄清一下? - Alex Walczak
2个回答

7

这仅适用于字符串字面值

字符串字面值隐式创建一个类型为char[N]的数组对象,其中包含字面值后跟终止字符'\0'。该对象具有静态存储期并且是只读的(由于历史原因,它不是const,但尝试修改它会产生未定义的行为)。

当您编写以下内容时:

char *ptr = "abc";

你正在创建一个指针对象ptr,并将其初始化为指向只读静态数组"abc"的地址。(你可以通过定义它为const来防止修改。)
当你写下以下代码时:
char arr[] = "abc";

你正在创建一个char[4]类型的数组对象arr,并且将静态只读数组的内容复制到该对象中。 arr 不是只读的。
int array[] = {1, 2, 3};

创建一个数组对象并按照所示进行初始化。没有像字符串字面量那样的“整数数组字面量”。(几乎有——请参见“复合字面量”——但这些不具有与字符串字面量相同的只读语义。)
请注意这一点:
char t[3] = "abc";

这是一个特殊情况:如果数组用字符串字面值初始化,并且没有足够的空间放置终止符'\0',那么只有非空字符被复制到数组中。因此,t不包含一个字符串,只是一个未终止的字符序列。这与你的问题无关。


谢谢!这个话题有点偏离,但你写道:“你可以通过将[char* ptr = “abc”]定义为const来防止修改。”任何试图修改char* ptr = "abc"(没有使用const)的尝试都已经失败,所以请问你具体指的是什么?编辑:我可能忽视了在我的计算机之外,程序没有使用const前缀的可能性。 - Alex Walczak
1
如果你写了 char *s = "abc"; s[0] = 'A';,你很可能会遇到运行时崩溃。(实际上,这种行为是未定义的;某些实现可能无法捕获它。)如果相反地你写 const char *s = "abc"; s[0] = 'A';,那么编译器将会捕获错误。尽早捕获错误(几乎)总是更好的。 - Keith Thompson

1

对于其他数组类型,没有像字符串字面量一样的确切类比。但是您可以通过使用带有const限定符的复合字面量来接近一些。

const int *p = (const int []) { 1, 2, 3 };

有可能会将其放入只读内存中,如果试图修改它(在去除constness后),程序可能会崩溃。与字符串字面量的另一个相似之处是,带const限定符的复合字面量可能共享存储空间。

复合字面量和字符串字面量之间的一个明显区别是,字符串字面量始终具有静态存储期,而块级复合字面量具有自动存储期。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接