Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么可以将常量字符*分配给字符*?_C++_String_Char_Literals - Fatal编程技术网

C++ 为什么可以将常量字符*分配给字符*?

C++ 为什么可以将常量字符*分配给字符*?,c++,string,char,literals,C++,String,Char,Literals,我知道,例如“hello”是const char*类型。因此,我的问题是: 我们如何将像“hello”这样的文字字符串分配给非常量字符*,如下所示: char* s = "hello"; // "hello" is type of const char* and s is char* // and we know that conversion from const char* to // char* is inv

我知道,例如
“hello”
const char*
类型。因此,我的问题是:

  • 我们如何将像
    “hello”
    这样的文字字符串分配给非
    常量字符*
    ,如下所示:

    char* s = "hello";  // "hello" is type of const char* and s is char*
                        // and we know that conversion from const char* to
                        // char* is invalid
    
  • 是像
    “hello”
    这样的文本字符串,它将占用我所有程序中的内存,还是像语句结束时将被销毁的临时变量

  • 事实上,
    “hello”
    属于
    字符常量[6]
    类型

    但是问题的要旨还是正确的——为什么C++允许我们将只读内存位置分配给非代码> const 类型?

    唯一的原因是向后兼容旧的C代码,它不知道
    const
    。如果C++在这里严格,它就会破坏很多现有代码。 也就是说,大多数编译器可以配置为警告此类代码已弃用,甚至在默认情况下也可以这样做。此外,C++11完全不允许这样做,但编译器可能还没有强制执行


    对于标准球迷:
    [参考文献1]C++03标准:§4.2/2

    不是宽字符串文字的字符串文字(2.13.4)可以转换为“指向字符的指针”类型的右值;宽字符串文字可以转换为“指向wchar\u t的指针”类型的右值。无论哪种情况,结果都是指向数组第一个元素的指针。仅当存在显式适当的指针目标类型时,才考虑此转换,而不是在通常需要从左值转换为右值时。[注意:此转换不推荐使用。参见附录D.]为了在重载分辨率(13.3.3.1.1)中排名,此转换被视为一个数组到指针的转换,然后是一个限定转换(4.4)。[示例:“abc”作为数组到指针的转换转换为“指针到常量字符”,然后作为限定转换转换为“指针到字符”。]

    C++11只是删除了上面的引号,这意味着它在C++11中是非法代码

    [参考文献2]C99标准6.4.5/5“字符串文字-语义”:

    在翻译阶段7中,将值为零的字节或代码附加到由字符串文字产生的每个多字节字符序列中。然后使用多字节字符序列初始化静态存储持续时间和长度刚好足以包含该序列的数组。对于字符串文字,数组元素具有char类型,并使用多字节字符序列的各个字节进行初始化;对于宽字符串文字,数组元素的类型为wchar\u t,并使用宽字符序列初始化

    如果这些数组的元素具有适当的值,则未指定这些数组是否不同如果程序试图修改这样的数组,则行为未定义。


    只需使用
    字符串

    std::string s("hello");
    
    <>这就是C++的方式。如果确实必须使用
    char
    ,则需要创建一个数组并在其上复制内容

    像“hello”这样的文本字符串会占用我所有程序的内存,就像一个临时变量,在语句结束时会被销毁

    它保存在程序数据中,所以它在程序的生命周期内是可用的。您可以从当前作用域返回此数据的指针和引用


    const char*
    被强制转换为
    char*
    的唯一原因是与c兼容,就像winapi系统调用一样。与任何其他常量转换不同,此转换是未经验证的。

    在您的示例中,您不是赋值,而是构造。例如,std::string确实有一个
    std::string(const char*)
    构造函数(实际上它更复杂,但这并不重要)。同样,char*(如果它是一个类型而不是指向类型的指针)可以有一个const char*构造函数,它正在复制内存


    我不知道编译器在这里是如何工作的,但我认为它可能类似于我上面描述的:
    “Hello”的副本
    在堆栈中构造,
    s
    用该副本的地址初始化。

    第二个问题的答案是变量
    s
    作为指向char的类型指针存储在RAM中。如果它是全局的或静态的,它将被分配到堆上,并在运行程序的生命周期内保持在那里。如果它是一个局部(“自动”)变量,它将被分配到堆栈上,并一直保留到当前函数返回为止。在任何一种情况下,它都会占用容纳指针所需的内存量

    字符串
    “Hello”
    是一个常量,它与所有其他常量和初始值设定项一起存储为程序本身的一部分。如果您将程序构建为在设备上运行,则字符串将存储在ROM中


    请注意,由于字符串是常量且
    s
    是指针,因此无需复制。指针
    s
    只指向存储字符串的任何位置。

    这只允许与C兼容。一般来说,C++被认为是不受欢迎的,优秀的编译器会给出警告。从标准中添加相关的引用。希望你不会介意。调试模式中的MSVC会阻止你在运行时编写一个字符串文字,在编译时(如果可以)编写GCC。但是,有一个选项,我相信是-wwrite strings或类似的东西打开兼容模式,并将字符串文本置于R/W中memory@Als你把一件简单的东西弄得很丑但是谢谢。实际上我也想补充一下,但我在我的C++11草稿中根本找不到相关的段落。2.14.3确实定义了类型,附录规定了转换的无效性,但没有任何证据表明这是不推荐的,但在C++03中有效。@KonradRudolph;所以“hello”是char-const[6],它衰减为const-char*