【问题标题】:Why does const char[] get converted to const char* all the time?为什么 const char[] 一直被转换为 const char*?
【发布时间】:2020-03-18 19:59:47
【问题描述】:

所以,我知道字符串文字的类型为const char[N]。而且我也知道,如果我们在某个函数中有const char[] 参数,编译器会自动将其转换为const char*

但是为什么我总是收到编译器错误消息说字符串文字的类型为const char*

这里有几个例子:

void f(int x) {}
int main()
{
    f("Hello");
    return 0;
}

错误:invalid conversion from 'const char*' to 'int'

void f() {
    throw "Hello";
}
int main()
{
    try{ f(); } catch (int x) { std::cout << "No\n";}
    return 0;
}

在终端:terminate called after throwing an instance of 'char const*'

编辑:我正在使用 GNU GCC。

【问题讨论】:

标签: c++ string-literals


【解决方案1】:

为什么 const char[] 总是被转换成 const char*?

一般情况下,因为你提到的功能参数调整还有一个密切相关的规则:

[conv.array] 数组到指针的转换

“N T 的数组”或“T 的未知边界数组”类型的左值或右值可以转换为“指向 T 的指针”类型的纯右值。 应用临时实现转换 ([conv.rval])。 结果是指向数组第一个元素的指针。

[basic.lval] 值类别

当一个左值作为一个操作数的操作数出现时,该操作数需要一个纯右值,左值到右值、数组到指针或函数到指针的标准转换是应用于将表达式转换为纯右值。

通俗地说,这种隐式转换称为指针衰减

错误消息似乎描述了将左值到右值转换的中间结果转换为参数类型的尝试。

在终端中:在抛出 'char const*' 的实例后调用终止

在这种抛出异常的特殊情况下,有一个特定的规则,它与指针衰减基本相同,但在抛出的上下文中:

[expr.throw] 抛出异常

使用操作数计算 throw 表达式会引发异常; 异常对象的类型由从操作数的静态类型中删除任何顶级 cv 限定符并从“T 数组”或函数中调整类型来确定键入 T 到“指向 T 的指针”

所以,调整后的异常对象类型其实是const char*,编译器生成的消息描述的就是这个未捕获的对象。


为了完整起见,这里是你知道的参数调整规则:

[dcl.fct] 函数

...确定每个参数的类型后,将任何类型为“T数组”或函数类型T的参数调整为“指向T的指针”

附:异常处理程序也有类似的调整规则:

[except.handle] 处理异常

类型为“T 数组”或函数类型 T 的处理程序被调整为类型“指向 T”的指针。

【讨论】:

  • 这解释了异常消息,但我不明白这如何解释为什么 gcc 将字符串文字称为const char*,而 msvc 和 clang 将它(更正确?)称为@987654323 @.
  • @churill GCC是指调整后抛出的异常对象的类型,Clang是指调整前的表达式类型。在我看来,两者都是正确的,我不认为哪个更有用。
  • @eerorika 这种“自动”数组到指针的转换是否使用临时对象进行?如果不是,那么转换如何发生在略低的水平上?
  • @domocar1 使用临时对象也会发生这种情况。
  • 也是?有什么选择?我没有从你的回答中发现它,可能是因为我缺乏知识。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-16
  • 1970-01-01
  • 1970-01-01
  • 2010-09-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多