0

在下面的程序中,p 被声明为一个指针(它是常量但字符串不是)。但程序仍然无法工作并突然停止说“untitled2.exe 已停止工作”。

#include<stdio.h>
#include<stdlib.h>

int main(){
    char * const p = "hello";
    *p = 'm';
    return 0;
}

为什么会出现这种意外行为?

4

3 回答 3

5

尽管p它本身是一个指向非const对象的指针,但它指向的是一个字符串字面量。字符串文字是一个对象,尽管const其类型没有限定,但它是不可变的。

换句话说,p是指向一个不是 的对象const,但表现得好像它是一样。

阅读更多关于 ANSI/ISO 9899:1990 (C90),第 6.1.4 节的内容。

于 2013-06-17T03:33:15.407 回答
5

您收到 Windows 错误,因为您无效地访问内存。在其他系统上,您可能会收到 SEGFAULT 或 SEGV 或总线错误。

*p = 'm';

正在尝试将常量字符串“hello”的第一个字母从“h”更改为“m”;

于 2013-06-17T00:58:49.117 回答
2
char * const p = "hello";

定义一个常量指针,并用一个本质上是 typep的常量字符串的内存地址初始化它。通过此分配,您将丢弃限定符。它是有效的 C,但如果您不知道自己在做什么,则会导致未定义的行为。"hello"const char *const

注意const char *禁止你修改被指向内存的内容,但不禁止修改地址,char * const允许你修改内容,但固定地址。还有一个组合版本const char * const

尽管这是有效的 C 代码,但取决于您的操作系统位置和对其的限制,"hello"可能会或可能不会最终进入可写内存。这是未定义的。根据经验:常量字符串是可执行程序文本的一部分并且是只读的。因此尝试写入*p会给您一个内存权限错误SIGSEGV

正确的方法是将字符串的内容复制到堆栈并在那里工作:

char p[] = "hello";

现在您可以修改*p,因为它位于可读写的堆栈上。如果您需要全局相同,则将其放入全局范围。

于 2013-06-17T10:39:33.187 回答