2014-12-03 50 views
21

所有编译我试图正确地拒绝代码为什么'int x = +“foo”;'类型错误,但不是语法错误?

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

与一种类型的误差:const char[4]不能转换到int。为什么,同样的编译器(包括Ideone.com)给予相同错误

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

,而不是(因为我本来以为)语法错误的因为...标志+的?我的第一个想法是const char[4]衰减到一个指针,而指针又被视为一个整数值,所以+表示“正值”。虽然似乎有点牵强,但我预计会在错误消息中看到const char*

+0

http://ideone.com/LYHiH0将'x'改为'const char *'编译,显然这个加号不是语法错误。但我很想知道为什么。作为一个方面说明,在我的ideone中运行时,链接的错误表明'const char *'不能转换为'int',而不是'const char [4]'。 – IllusiveBrian 2014-12-03 15:41:51

回答

34

语法不涉及类型系统意义上的类型(整数和字符和指针),只包含关键字,运算符,表达式在语法上的类型。在C++语法中,+是可以在表达式之前的一元前缀运算符。 "foo"是一个表达式。因此,就解析器而言,+"foo"是一个有效的表达式。

你的想法,字符串常量衰变成一个指针和+是一个指针上的任何操作是正确的,下面的程序甚至可以编译和运行:

#include <iostream> 

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

...那是无关紧要的。你看到的是一个类型错误,而不是语法错误。

编辑或许更令人信服的是,你可以重载一元+事实:

#include <iostream> 

struct SomeType { 
    const char *operator+() const 
    { 
     return "Hello, world!\n"; 
    } 
}; 

int main() 
{ 
    SomeType x; 
    std::cout << +x; 
} 
+0

我以某种方式假定'+'是一个一元前缀运算符,它只能在数字文字之前(即在解析时容易检测到的东西)。它没有发生在我之前,它可以在任何表达之前! – 2014-12-03 15:49:08

+0

@FrerichRaabe你甚至可以重载它,看到更新的答案:) – 2014-12-03 15:52:38

+3

有趣的事实包括由于负面或正面的迹象是一般操作符而不是文字的语法的一部分,C++实现基于二进制补码表示整数,所以不可能将有符号类型的最负值表示为否定字面值。例如,对于16位“int”,表达式“-32768”相当于“0-32768”,其涉及超出范围的正值32768:无效。 – 2014-12-03 15:59:36

9

一元+适用于指针,它只是返回类型的值并且不执行上的指针积分促销所以结果是一个指针不是一个整数类型,从C++草案标准部5.3.1一元运算符

The operand of the unary + operator shall have arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument. Integral promotion is performed on integral or enumeration operands. The type of the result is the type of the promoted operand.

文字串是常量字符的阵列,从2.14.5字符串文字

[...]A narrow string literal has type “array of n const char”,[...]

这将衰减在此上下文中的指针。

+1

感谢您指出相关的标准部分。 – 2014-12-03 15:49:56

7

一元+操作者可以应用到指针类型:

C++11 5.3.1 [expr.unary.op]/7: The operand of the unary + operator shall have arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument.

所以字面阵列被转换为const char *,并且操作者施加到该指针,不能将指针分配给int正如前在第一个例子中。

+0

有趣的是,使用Visual Studio 2012编译我的测试程序会产生错误消息:const char [4]不能转换为int,即指针衰减在错误消息中不再可见(Ideone.com似乎使用了一个编译,尽管使用'const char *')。 – 2014-12-03 15:51:06

4

Why is 'int x = + “foo”;' a type error but not a syntax error?

因为没有语法错误。存在语义错误。

解析语句后,编译器确定此类初始化是否可用。实际上在语法上,该语句看起来像

int x = + (expression); 

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