关于`&"hello"`和`"hello"`类型的问题

Question about the type of `&"hello"` and `"hello"`

根据 this code snippet 的输出,&"hello" 的类型是 const char(*)[6],因此 char* ptr = &"hello"; 对于 char* 和 [=15= 是非法的] 是不同的类型。

并且由于 char* ptr1 = "hello"; 使用 C++11 及更高版本编译,"hello" 的类型是 char*?

如果"hello"的类型是char*,那么&"hello"不应该是指向char*的指针(即char**)?

我曾经写过 char* ptr1 = "hello"; 很多年,当我知道“hello”是纯右值时。问题是我可以获取字符串literal.After的地址我发现&"hello"的类型是const char(*)[6],我现在一头雾水

有人能解释一下这件事吗?

这是上述代码片段:

#include<memory>
#include<thread>
#include<iostream>
#include<typeinfo>

int main()
{
    char* ptr = &"hello";
    char* ptr1 = "hello";
}

这是编译器的抱怨:

<source>: In function 'int main()':
<source>:8:17: error: cannot convert 'const char (*)[6]' to 'char*' in initialization
    8 |     char* ptr = &"hello";
      |                 ^~~~~~~~
      |                 |
      |                 const char (*)[6]
<source>:9:18: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
    9 |     char* ptr1 = "hello";
      |                  ^~~~~~~

更新: 感谢 ShadowRanger 的澄清。我意识到字符串文字的类型是 const char[6].

"Hello" 是类型 const char [6]string literal,由于 类型, 衰减 const char*衰减.

现在让我们看看您程序中的每个语句都发生了什么。

案例一

这里我们考虑语句:

char* ptr = &"hello";

正如我所说,"hello"const char [6] 类型。因此,在其上应用运算符 & 的地址会得到一个 const char (*)[6] ,它被读取为一个 指向大小为 6 且元素类型为 const char[= 的数组的指针71=].

这意味着右侧(const char (*)[6])和左侧(char*)的类型不匹配。由于没有从 const char (*)[6]char* 的隐式转换,因此编译器给出了上述错误:

cannot convert 'const char (*)[6]' to 'char*'

案例二

这里我们考虑语句:

char* ptr1 = "hello"; //invalid C++

因为 "Hello"const char[6] 类型,这意味着数组中的 char 元素是不可变的(或 non-changable)。正如我所说,类型 const char[6] 衰减为 const char*。因此在右侧我们有一个 const char*。因此,如果我们被允许写 char* ptr1 = "Hello"; 那么这意味着我们可以更改数组的元素,因为 ptr1 上没有 low-level const。因此,允许 char* ptr1 = "Hello"; 将允许更改标记为 const 的数据,这不应该发生(因为数据不应更改,因为它被标记为 const)。这就是为什么提到的警告说:

ISO C++ forbids converting a string constant to 'char*'

因此,为了防止这种情况发生,我们必须添加一个 low-level const,如下所示:

vvvvv---------------------------> note the low-level const
const char* ptr1 = "Hello";  //valid c++

这样就不允许指针ptr1改变const标记的数据。 通过添加上面突出显示的 low-level const,这意味着我们不允许更改数组的基础字符。