在下面的程序中,p被声明为一个指针(它是常量但不是字符串)。但程序仍无法正常工作并突然停止说“untitled2.exe已停止工作”。
#include<stdio.h>
#include<stdlib.h>
int main(){
char * const p = "hello";
*p = 'm';
return 0;
}
为什么会出现这种意想不到的行为?
答案 0 :(得分:5)
您收到Windows错误,因为您无效访问内存。在其他系统上,您可能会收到SEGFAULT或SEGV或总线错误。
*p = 'm';
尝试将常量字符串“hello”的第一个字母从“h”更改为“m”;
答案 1 :(得分:5)
虽然p
本身是指向非const
对象的指针,但它指向一个字符串文字。字符串文字是一个对象,虽然不是const
- 对其类型有资格,但是是不可变的。
换句话说,p
指的是一个不是const
的对象,但表现得好像一样。
阅读更多关于ANSI / ISO 9899:1990(C90)的6.1.4节。
答案 2 :(得分:2)
char * const p = "hello";
定义一个常量指针p
,并使用常量为"hello"
的常量字符串const char *
的内存地址对其进行初始化。通过此任务,您将丢弃const
限定符。它是有效的C,但如果您不知道自己在做什么,将会导致未定义的行为。
请注意const char *
禁止修改指向的内存内容,但不禁止更改地址,而char * const
允许您修改内容,但修复了地址。还有一个组合版本const char * const
。
虽然这是有效的C代码,但根据您的操作系统位置和对"hello"
的限制,它可能会或可能不会在可写内存中结束。这是未定义的。作为拇指的规则:常量字符串是可执行程序文本的一部分,并且是只读的。因此,尝试写入*p
会给您一个内存权限错误SIGSEGV
。
正确的方法是将字符串的内容复制到堆栈并在那里工作:
char p[] = "hello";
现在您可以修改*p
,因为它位于可读/写的堆栈中。如果您需要全局相同,则将其放入全局范围。