C++ c++;带运算符[]的常量指针

C++ c++;带运算符[]的常量指针,c++,pointers,operator-keyword,C++,Pointers,Operator Keyword,第一条语句创建一个由常量指针p指向的字符串,第二条语句尝试修改该字符串,编译器接受该字符串,而在运行时,会弹出一个访问冲突异常,有人能解释原因吗?因此,您的问题有两个方面: 为什么它会给出访问冲突:在可执行程序的代码页中,字符文本字符串作为文本存储;大多数现代操作系统不允许更改这些页面(包括MS windows),因此保护故障 为什么编译器允许它:在这个上下文中,const关键字指的是指针,而不是它指向的东西。代码,如p=“Hello”;将导致编译器错误,因为您已将p声明为常量(不是*p)。如果

第一条语句创建一个由常量指针p指向的字符串,第二条语句尝试修改该字符串,编译器接受该字符串,而在运行时,会弹出一个访问冲突异常,有人能解释原因吗?

因此,您的问题有两个方面:

  • 为什么它会给出访问冲突:在可执行程序的代码页中,字符文本字符串作为文本存储;大多数现代操作系统不允许更改这些页面(包括MS windows),因此保护故障

  • 为什么编译器允许它:在这个上下文中,const关键字指的是指针,而不是它指向的东西。代码,如p=“Hello”;将导致编译器错误,因为您已将p声明为常量(不是*p)。如果您想将它指向的对象声明为常量,那么您的声明应该是const char*p

  • char* const p = "world";
    p[2] = 'l';
    
    p指向常量字符数组,它位于.rodata内存区域中。因此,不能修改p变量所指向的数据,也不能将p更改为指向其他字符串

      char* const p = "World";
    
    这里p是一个具有恒定内存地址的指针。所以这将很好地编译,因为根据编译器,并没有语法错误,并且它在运行时bcoz中抛出异常,因为它是一个常量指针,您可以更改它的值


    问题是,如果您定义如下字符串文字:

    char* const p = "world";
    
    编译器将只为指针和文本位置准备内存 将默认设置为.text节

    另一方面,如果您将其定义为:

    char * p = "some text"
    
    编译器将知道您需要整个字符数组的内存

    在第一种情况下,您无法读取该值,因为内存的.text部分的MMU设置为只读访问,在第二种情况下,您可以自由访问和修改内存

    另一个想法(防止运行时错误)是正确描述指针指向的内存

    对于常量指针,它将是:

    char p[] = "some text"
    
    对于正常的情况:

    const char * const p = "blaaaah"
    

    这在当前C++标准(C++ 11)中是非法的。大多数编译器仍然接受它,因为它们默认使用了以前的C++标准(C++ 03),但是即使在那里,代码也被弃用,而一个具有正确警告级别的编译器应该对此发出警告。 原因是文字

    “world”
    的类型是
    字符常量[6]
    。换句话说,文字总是常量,不能更改。当你说

    char* const p = "world";
    
    …然后编译器将文本转换为指针。这是通过一个名为“数组衰减”的操作隐式完成的:一个C数组可以隐式转换为指向其开始的指针

    因此,
    “world”
    被转换为
    char const*
    类型的值。请注意
    常量
    –即使通过指针访问,也不允许更改文本

    唉,C++03还允许将文本分配给非
    const
    指针,以提供与C的向后兼容性

    因为这是一个面试问题,所以正确的答案是:代码是非法的,编译器不应该允许它。以下是更正后的代码:

    char* const p = "world";
    

    我们在这里使用了两个
    const
    s:第一个是文本所必需的。第二个使指针本身(而不是指向的值)
    const

    他将指针描述为常量,而不是指向内存中存储的值,因此他想要(const char*)。这里有一些混淆。数据内存受到保护,但不太可能位于代码段中。此外,这也解释了为什么代码在实践中失败,但它不能解释为什么C++中允许这种“无用”行为。你想要的是chp[]=“Word”而不是char * const pTalm,这是一个面试问题,我只是想知道为什么它是非法的。我认为@Elemental很有意思:您不能在运行时更改文本。我发现即使是char*p=“world”;也会导致失败。正如cerkiewny所说(它将文本复制到本地缓冲区,您可以安全地进行更改),或者您应该使用
    const char*p=“world”,防止在编译时尝试修改文本。注意,const位于*符号的左侧;char*const p=&str他可以修改它吗?@crush-没有-同样的问题-底层数据存储在内存页中,操作系统不允许修改。这实际上与编译器没有什么关系,更多的是与链接器如何安排内存和操作系统有关!如果他将
    str
    复制到另一个
    char[]
    ,然后指向新的
    char[]
    ,该怎么办!那么他肯定可以修改it@crush如果您的意思是
    char str[]=“World”
    那么是的,它会将文本复制到一个名为str的本地缓冲区中,该缓冲区可以修改。@crush yes-这就是我的理解。
    char p[]
    不在堆中。@NeilKirk yes,您的权利,如果它是全局变量,则将其视为自动变量。bss节指针p不会更改<代码>p[2]
    不会更改p的值。
    char* const p = "world";
    
    char const* const p = "world";
    //p[2] = 'l'; // Not allowed!