C语言中字符指针的困惑

5

C语言中的字符指针让我感到困惑。

假设我们有一个char类型的指针,它指向字符串常量的第一个字符。

char *a="ABCD";

然后我们不能使用指针 a 更改该字符的值,因为以下语句会导致段错误。

*a='X';

现在假设我们有一个 char 指针,它指向一个字符 常量

const char B='X';    
char *ptr=&B;

在这种情况下,我们可以使用语句更改该字符的值

*ptr='Z';

我的问题是,这是否是未定义行为证明C不够健壮的情况?还是有更深层次的逻辑涉及其中?

@EugeniuRosca 你的意思是 char const *a = "ABCD"。它们的语义不同。 - Quentin
const 表示内存是只读的。就这样。你不能通过另一个指针引用来更改它 - 这应该会生成编译器警告。 - jim mcnamara
1
请查看https://dev59.com/p3E85IYBdhLWcg3w1HKF。 - xp500
3个回答

7
假设C让您很容易地把自己脚打伤。但是修改B仍然是未定义的行为,就像修改*a一样,因为B已被声明为const。
为了帮助解决这个问题,在GCC上开启警告(除非在非常特殊的情况下,您应始终这样做)会产生以下警告:
warning: initialization discards 'const' qualifier from pointer
         target type [-Wdiscarded-qualifiers]

5
指针的行为不同之处在于,C程序有多个内存段,其中一些是受保护的。
由于字符常量放置在受保护的段中,因此我们不能使用指针a更改该字符的值,以下语句会导致分段错误。
与其他常量不同,字符串常量被放置在受保护的段中。任何尝试修改此段的操作都会导致未定义的行为(即您的程序可能会发生段错误)。
由于指针指向一个字符串常量,它指向的值无法修改。如果通过使用数组将常量强制复制到可修改的内存中,则允许进行相同的修改:
char a[]="ABCD";
*a='X';

我们可以使用语句来改变那个单个字符的值,这是因为字符常量总是被复制到可修改的内存中。

5
在C语言中,不允许修改字符串字面量。
char *a="ABCD";  

等同于

char const *a="ABCD";  

*a='X'; 修改了字符串字面量 ABCD。而在第二种情况中,ptr 指向一个不应被更改的字符,*ptr='Z'; 会修改包含字符 X 的位置,这也是无效的。

请注意,修改一个 const 限定的对象是一种约束违规行为。


1
修改 *ptr 毫无意义。 - Quentin
@Quentin;糟糕!同意。漏掉了const限定符。 - haccks

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