【问题标题】:"hello world" string literal can be assigned to char * type?“hello world”字符串文字可以分配给char *类型吗?
【发布时间】:2012-10-26 06:00:43
【问题描述】:
char* foo = "fpp"; //compile in vs 2010 with no problem

虽然字符串文字是 const char* 类型。
并且 const 类型不能分配给非 const 类型。
所以我预计上面的代码会失败还是我遗漏了什么?

编辑:对不起,我完全忘记了编译器也会抛出警告。
我一直在查看错误列表。
我忘记检查了。

Edit2:我将我的项目警告级别设置为 EnableAllWarnings (/Wall),但没有任何警告。
所以我的问题仍然有效。

【问题讨论】:

  • 只是为了确定(我看到 C++ 标签)C 或 C++ 程序?
  • 我相信它只会抛出警告,如果你指定 char*=const char*...
  • 你能不能试着写一个最小的代码,编译成 .o 并获取 .o 文件的 objdump ;只是看看这个 fpp 是驻留在 RO 内存中还是在 RAM 中。
  • gcc 只是给出警告而不是错误:liveworkspace.org/code/b7aea430807569a60acfaa1e6276b03e - 你在 VS2010 中检查过警告吗?
  • 我只能猜测 - 但我认为这是出于与 C-API 的兼容性原因。这实际上是绝对必要的,因为写入 foo[1](例如 foo[1]='l';)因访问冲突而失败。而VS2010甚至没有给出警告。

标签: c++ string constants


【解决方案1】:

C++03 弃用[Ref 1] 使用不带 const 关键字的字符串文字。

[参考 1]C++03 标准:§4.2/2

不是宽字符串文字的字符串文字(2.13.4)可以转换为“指向char的指针”类型的右值;宽字符串文字可以转换为“指向 wchar_t 的指针”类型的右值。无论哪种情况,结果都是指向数组第一个元素的指针。仅当存在显式适当的指针目标类型时才考虑这种转换,而不是当一般需要从左值转换为右值时。 [注意:此转换已弃用。见附录 D。] 为了在重载决议 (13.3.3.1.1) 中排名,这种转换被认为是数组到指针的转换,然后是限定转换 (4.4)。 [示例:“abc”转换为“pointer to const char”作为数组到指针的转换,然后转换为“pointer to char”作为限定转换。 ]

C++11 只是删除了上面的引用,暗示它是 C++11 中的非法代码。

在 C++03 之前,C++ 派生了它的字符串字面量声明,没有 const 关键字,请注意,这在 C 中完全有效。

【讨论】:

    【解决方案2】:

    据我了解,在 C 中,在添加 const 之前,这是将字符串分配给指针的方式。

    在 C++ 中,这是已弃用 的行为,但仍允许保持向后兼容性。所以不要使用它。

    其实我相信C++11是完全无效的。

    【讨论】:

    • 好的,我明白了。C++ 向后兼容 C,而 const 仅在 C++ 中添加。这是有道理的。
    【解决方案3】:

    不完全是。字符串文字可分配给 char* 类型。不应修改字符串文字。

    这种奇怪的情况是为了向后兼容const之前的程序。

    【讨论】:

    • 不知道为什么我认为它是正确的而被否决?
    • @LuchianGrigore,好的,我会修改我的答案。
    • @Luchian:谢谢——这就是为什么不解释就投反对票没有帮助的原因。
    • @PaulR 我同意。 99% 的时间我都会发表评论,但最初的答案是“不完全。字符串文字是 char* 类型。”......在这种情况下,评论将是多余的。
    【解决方案4】:

    gcc -std=c++0x 对此发出警告:

    a.cpp:5:14: 警告:不推荐将字符串常量转换为 'char*' [-Wwrite-strings]

    因此,这仍然是允许的,但已弃用,因为文字字符串是 const。

    【讨论】:

      【解决方案5】:

      没有 const 类型这样的东西。 const 关键字是所谓的类型限定符。它可以应用于任何指针类型,只是意味着指针指向的值不应该被修改。

      您也可以通过这种方式将 const 限定符应用于指针引用本身:

      char* const p ="aaa";
      

      这将保护指针变量不指向另一个字符串。

      【讨论】:

        【解决方案6】:

        有一个特殊的隐式转换来支持这一点,因为它是遗留代码中的一个常见习惯用法(通常在const 存在之前编写)。您的字符串文字的类型是char const[],您应该只使用它。一个好的编译器会在上面发出警告,因为转换从引入的那一刻起就被弃用了。

        请注意,这与 C 不同,其中字符串文字的类型是 char[](但尝试修改它仍然是未定义的行为)。

        【讨论】:

          【解决方案7】:

          您说的是 C 字符串,实际上是 char 的向量。在 C++ 中,使用了 std::string 类,并创建了一个常量字符串为 const std::string

          无论如何,编译器会在未来的程序中保留一块内存,以便存储出现在源代码中的文字字符串。这部分内存被认为是只读的,所以你应该用const char * 指向它。它的大小正好是字符串的大小加上尾随零的一个额外位置,标记字符串的结尾。

          编译器需要保持向后兼容性,因此它们仍然接受char * 指向的文字。但是,这是一种误导,因为您不应该能够修改可以存储在嵌入式系统 ROM 中的内存。

          在我的系统中,我使用 clang:

          $ clang --version
          Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0)
          Target: i386-pc-linux-gnu
          Thread model: posix
          

          在clang C编译器中,这段代码编译没有错误:

          #include <stdio.h>
          #include <stdlib.h>
          
          int main()
          {
              char * str = "Hello, World!";
          
              printf( "%s", str );
          
              return EXIT_SUCCESS;
          }
          

          但是,同样的代码(稍作修改,例如标头名称)在编译为 C++ 程序时会引发以下警告:

          kk.cpp:6:15: warning: conversion from string literal to 'char *' is deprecated [-Wdeprecated-writable-strings]
                  char * str = "Hello, World!";
                               ^
          1 warning generated.
          

          希望这会有所帮助。

          【讨论】:

            猜你喜欢
            • 2011-09-23
            • 1970-01-01
            • 2019-09-06
            • 2016-10-25
            • 2021-02-22
            • 2020-04-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多