C++ 为什么是';int x=+&引用;“福”';类型错误,但不是语法错误?

C++ 为什么是';int x=+&引用;“福”';类型错误,但不是语法错误?,c++,C++,我尝试的所有编译器都正确地拒绝了代码 int main() { int x = "foo"; } 类型错误:const char[4]无法转换为int。为什么相同的编译器(包括)会为 int main() { int x = + "foo"; } 而不是(如我所想)由于+符号而导致的语法错误?我的第一个想法是const char[4]衰减为指针,指针又被视为整数值,因此+表示“正”。不过似乎有点牵强,我希望看到const char*出现在错误消息中。语法不涉及类型系统意义上的类型(i

我尝试的所有编译器都正确地拒绝了代码

int main() {
  int x = "foo";
}
类型错误:
const char[4]
无法转换为
int
。为什么相同的编译器(包括)会为

int main() {
  int x = + "foo";
}

而不是(如我所想)由于
+
符号而导致的语法错误?我的第一个想法是
const char[4]
衰减为指针,指针又被视为整数值,因此
+
表示“正”。不过似乎有点牵强,我希望看到
const char*
出现在错误消息中。

语法不涉及类型系统意义上的类型(int、chars和指针),只涉及语法意义上的关键字、运算符和表达式。在C++语法中, +/Cuth>是一个可以在表达式前面的一元前缀运算符。代码>“foo”是一个表达式。因此,就解析器而言,
+“foo”
是一个有效的表达式

您认为字符串常量会衰减为指针,
+
是指针上的不可操作的想法是正确的,下面的程序甚至会编译并运行:

#include <iostream>

int main()
{
    const char *message = +"Hello!\n";
    std::cout << message;
}

一元<代码> +/>代码适用于指针,它只返回类型的值,不执行指针的积分提升,因此结果是指针,不是整数类型,从草案C++标准部分<代码> 5.3.1 < /代码>一元运算符:

一元+运算符的操作数应具有算术、无范围 枚举或指针类型,结果是 论点整数升级是对整数或枚举执行的 操作数。结果的类型是提升的操作数的类型

字符串文字是常量字符的数组,来自
2.14.5
string文字:

[…]窄字符串文字的类型为“n常量字符数组”[…]


在此上下文中,它将衰减为指针。

一元
+
运算符可应用于指针类型:

C++11 5.3.1[expr.unary.op]/7:一元+运算符的操作数应具有算术、无范围枚举或指针类型,结果为参数值

因此,文本数组被转换为
const char*
,并将运算符应用于该指针,然后无法像第一个示例中那样将指针分配给
int

为什么“intx=+”foo“;”类型错误,但不是语法错误

因为没有语法错误。有一个语义错误

解析语句后,编译器确定是否可以进行此类初始化。事实上,从句法上看,该语句如下所示

int x = + ( expression );

从句法上来说,这句话是正确的。此外,一元加号可以应用于指针

x
更改为
const char*
会编译,因此加号显然不是语法错误。我很想知道为什么。作为旁注,在我的ideone中运行时,您链接的错误是,
const char*
不能转换为
int
,而不是
const char[4]
。我不知怎的假设,
+
是一元前缀运算符,只能在数字文本之前(即,在解析时容易检测到的东西)。我没想到它可以出现在任何表达式之前@FrerichRaabe您甚至可以重载它,请参见更新的答案:)有趣的事实包括,由于负号或正号是通用运算符,而不是文字语法的一部分,用C++实现基于两个整数的互补表示,不可能把一个带符号类型的最负值表示为一个负文字。例如,对于16位
int
,表达式
-32768
相当于
0-32768
,其中包含超出范围的正值32768:invalid。这与@cheers和hth.-Alf建议的不完全一样:对于16位
int
,表达式
-32768
是一元
-
运算符对十进制常量
32768
的应用
32768
不能放入
int
,因此它具有类型
long
,对
long
求反将产生另一个
long
<代码>-32768因此始终具有预期值,但不总是预期类型。之所以产生这个问题是表达式<代码> -922337203685477580 < /C>,因为<代码> 922337203685477580 < /C>可能不适合任何有符号整数类型。语法实际上涉及C++中的类型…有趣的是,使用Visual Studio 2012编译我的测试程序时会产生一条错误消息,即
const char[4]
无法转换为
int
,即指针衰减的事实在错误消息中不再可见(Ideone.com似乎使用了使用
const char*
的编译)。
int x = + ( expression );