字符串字面量:指针 vs. 字符数组

18

在这个语句中:

char *a = "string1"

什么是字符串字面值?这是string1吗?因为这个线程What is the type of string literals in C and C++?说了不同的东西。

据我所知

int main()
{
    char *a = "string1"; //is a string- literals allocated memory in read-only section.
    char b[] = "string2"; //is a array char where memory will be allocated in stack.

    a[0] = 'X'; //Not allowed. It is an undefined Behaviour. For me, it Seg Faults. 
    b[0] = 'Y'; //Valid. 

    return 0;
} 

请在以上提到的要点之外添加一些细节。谢谢。

调试输出显示错误在于 a[0] = 'Y';

Reading symbols from /home/jay/Desktop/MI/chararr/a.out...done.
(gdb) b main
Breakpoint 1 at 0x40056c: file ddd.c, line 4.
(gdb) r
Starting program: /home/jay/Desktop/MI/chararr/a.out 

Breakpoint 1, main () at ddd.c:4
4   {
(gdb) n
6   char *a = "string1";
(gdb) n
7   char b[] = "string2";
(gdb) 
9   a[0] = 'Y';
(gdb) 

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400595 in main () at ddd.c:9

1
@elyashiv,这段代码是非法的,因为它试图修改一个字符串常量。 - hmjd
3
我不确定确切的问题是什么。关于字符串字面值的具体细节,请参阅C99标准的第6.4.5节。 - hmjd
也许这个stackoverflow问题可以帮助,或者这个问题 - Richard
1
你已经知道修改字符串字面量是未定义行为,幸运的是当你尝试这样做时会得到段错误。GDB 显示你在修改它时得到了段错误。这里有什么问题吗? - P.P
好的,从技术上讲,char *a = "string1"; 应该生成一个编译器警告,警告关于用 const char * 值初始化 char * 的问题。我猜测之所以没有警告,是因为太多的遗留代码将开始抛出警告。 - Edward Falk
1个回答

32
你可以将字符串字面量看作是“由双引号括起来的字符序列”。这个字符串应该被视为只读,试图修改这块内存会导致未定义的行为。它不一定存储在只读内存中,类型是char[]而不是const char[],但仍然是未定义的行为。类型不是const的原因是向后兼容。C语言一开始没有const限定符。在C++中,字符串字面量的类型是const char[]

那么为什么会出现分段错误?

  • 主要问题在于char *ptr = "string literal"ptr指向存储字符串字面量的只读内存。所以当你尝试访问这块内存:ptr[0] = 'X'(等同于*(ptr + 0) = 'X')时,会发生内存访问冲突
另一方面:char b[] = "string2"; 分配内存并将字符串 "string2" 复制到其中,因此修改它是有效的。当 b 超出范围时,该内存将被释放。
请查看字符数组的文字字符串初始化器

我只是想要更多关于它的细节。一些讨论让我感到困惑,比如char a[] = "sdsf"; 也是一个字符串字面值。 - Jeyaram
1
@rjayavrp: "字符串字面值是由双引号括起来的字符序列". 是的,在 char a[] = "sdsf"; 中,"sdsf" 是一个字符串字面值,用于初始化数组 a - LihO
谢谢。所以我误解了字符串字面量是在只读内存区域分配内存的字符串。它并不基于内存位置 :)。 - Jeyaram
1
@rjayavrp:“字符串字面量”只是一个术语。主要问题在于,您检索存储字符串字面量的只读内存的地址(char *ptr =“string literal”),然后尝试访问此内存:*(ptr + 1) ='A'... - LihO
那么,当我这样做时,为什么会收到这个警告:“使用类型为char [5]的表达式初始化const char的不兼容指针到整数类型”:const char myyear =“2014”;? - user749127
1
@moonman239:因为 const char myyear = "2014"const char *myyear = "2014" 是不同的东西。 - LihO

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