【问题标题】:No compilation error comparing integer with string?比较整数和字符串没有编译错误?
【发布时间】:2013-07-21 19:05:58
【问题描述】:

可能和很多人一样,我输入了这个错字

int a = 0;
cout << a < " "; //note the '<'

然而,MSVC++ 编译器只是抛出了一个警告

警告 C4552: '

虽然我预计会出现编译错误。它确实是标准的投诉代码吗?是否发生任何使代码有效的隐式类型转换或重载?我也很困惑&lt; 运算符是将字符串" " 与整数a 还是与cout &lt;&lt; a 的结果进行比较

一个相关的 SO 帖子是 here

【问题讨论】:

  • 您使用的编译器接受指针和整数类型比较,但标准禁止这样做。必要时更新或更改编译器
  • @a.lasram 如果没有,“NULL”宏将如何工作?
  • @a.lasram 没有。你搞错了优先级。
  • @kfsone 完全不相关,NULL 是一种特殊情况,因为literal-0(但只有literal-0)可以隐式转换为指针。
  • NULL 没有什么特别之处,它是一个定义为 0 的宏。他针对 0 进行了测试。这就是 C++11 添加“nullptr”和“std::nullptr_t”的原因。

标签: c++ compiler-errors compiler-warnings


【解决方案1】:

&lt;&lt; 运算符的优先级高于&lt;,因此解析为

(cout << a) < " ";

您并没有真正将字符串与整数进行比较。相反,您将ostream::operator&lt;&lt; 的返回值(即std::cout 本身)与字符串文字进行比较。这也是不合法的(从某种意义上说,它有一个未指定的结果,并且没有意义),clang 警告:

warning: result of comparison against a string literal is unspecified

它编译的原因是直到 C++11,std::ostream 可以隐式转换为void *。此外,const char[2] 类型的字符串文字衰减为const char * 类型的指针。所以,&lt; 操作符现在接受两个指针,这是允许的,尽管它的结果没有指定,因为这两个指针不指向同一个对象。

【讨论】:

  • 未指定!= 非法。
  • 有人请拍拍h2co3的背面,因为它比编译器更严格:D
  • @H2CO3:不喜欢语法上没有意义的东西很好,但你不能说它们是非法。实际上,C++ 标准并没有使用“非法”这个词,但我会说当且仅当需要符合标准的编译器来诊断它时,某些东西才是非法的。在 C 语言中,这是语法错误和约束违规;我认为 C++ 使用不同的术语。
  • @H2CO3:我的观点是,使用“非法”这个词来指代编译器可能会或可能不会警告的事情是对这个词的误用。也许“不正确”更接近您所表达的想法。
  • 可能值得指出为什么这是正式合法的。 x &lt;&lt; y 的返回值为std::ostream&amp;。没有运算符 &lt;std::ostream 作为其左操作数,因此编译器会查找转换。在 C++11 之前,有一个转换 std::istreamvoid*。并且指针比较是合法的(尽管结果是未指定的,除非两个指针指向同一个对象,这里不是这种情况)。我认为 C++11 已经解决了这个问题。
【解决方案2】:

实际上,因为它是(cout &lt;&lt; a) &lt; " ",所以我们将ostream" " 进行比较。 ostream 类有一个运算符将其转换为 void *。您可以将void *const char * 进行比较而不进行强制转换,因此编译器很乐意这样做,然后意识到您没有使用比较结果,并发出警告。

C++ 中那些古怪的东西之一。

【讨论】:

  • 但是@Ed Heal 说ostream 对象没有重载的&lt;。我在这里错过了什么吗?
  • 正确,它没有。所以编译器会找到一个可以比较的类型的转换——在本例中为operator (void *)
  • ostream operator void*(),但现在没有了。
【解决方案3】:

这取决于运营商precedence

该行等于(cout &lt;&lt; a) &lt; " "; - 因此&lt;" " 什么都不做!

编辑

该位返回一个对象(cout &lt;&lt; a) 返回一个ostream 类型的对象,其中它没有重载运算符&lt;,因此编译器要么放弃(C++11)要么挠头 amd 有一个bash 整数运算符(即指针等)。

【讨论】:

  • @H2CO3 或者更确切地说,为什么它在 C++11 中不再起作用了。在 C++11 之前,它工作得很好。
  • @KonradRudolph 我也是这么想的,但是 g++ 和 clang compile it anyway
  • 如果有关系,我使用的是 MSVC++ 2010,它似乎有很多 C++11 特性,但可能并不完全抱怨它。
  • @jrok stdlibc++ 实现有问题。该标准规定std::basic_ios 不再包含operator void*() const,而是包含explicit operator bool() const(第27.5.5.1 节)。 Using libc++ with clang++ does the right thing.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-03
  • 2014-11-28
  • 2018-03-24
相关资源
最近更新 更多