【问题标题】:Why is this simple program printing "1Hello World"? [duplicate]为什么这个简单的程序会打印“1Hello World”? [复制]
【发布时间】:2017-12-19 18:10:55
【问题描述】:

我仍在尝试进入 C++,并且我已经编写了以下代码:

#include <iostream>
using namespace std;

int main()
{

    cout << " "<< endl << cout << "Hello world!" <<endl;

}

输出是:

1Hello world!

为什么Hello World前面有一个1?

编辑:我的程序确实可以编译,看来我有一个旧的编译器版本。

【问题讨论】:

  • &lt;&lt; cout 不属于那里。状态operator () 正在cout 上进行评估,并以1 进行饲养
  • 如果它在运行我会很惊讶,你确定那是你的代码吗?没有为 ostreamostream 类型定义 operator&lt;&lt;
  • 是的,这里相当 emo:ideone.com/LElF24
  • 这个 sn-p 将在"Hello world!" pre-c++11 之前打印一个非空指针。它不会用 c++11 或更高版本编译。

标签: c++ iostream


【解决方案1】:

对您的问题的简短回答是您用于输出数据的语法略有偏差。如果将一堆输出语句链接在一起,则惯例是将流放在最左边并且不再重复。所以与其写

cout << " " << endl << cout << "Hello world!" << endl;
                       ~~~~~~~

随便写

cout << " "<< endl << "Hello world!" << endl;

您在这里看到1 的原因有点技术性。流类型都提供了一个重载运算符,您可以使用它来测试流是否有效。例如,你可以这样写:

if (cout) {
    // Everything is okay!
} else {
    // I don't know how you did it, but you broke cout and you can
    // no longer write anything to it!
}

(这通常用于 input 流,但输出流也支持这一点)。由于这种语法,如果您尝试将cout 插入输出流,C++ 将首先尝试将cout 转换为布尔值并打印该值。默认情况下,布尔值打印为 1 (true) 或 0 (false),因此您看到的 1 是 C++ 表示“是的,此流已启动并正在运行。”

(从技术上讲,重载的运算符会生成 void* 而不是 bool,但我现在将忽略该细节。)

请注意,现代版本的 C++(C++11 及更高版本)不支持此行为,如果您尝试使用现代编译器执行此操作,实际上会出现编译器错误。如果可能的话,我会建议您升级您的编译器版本,这会给您一个错误,而不是生成与您认为的不一样的代码。

【讨论】:

  • 我认为这将更多地属于语义而不是语法,尽管除此之外,什么编译器用于让它运行,它只会对我抛出错误
  • 单独使用现代编译器会产生编译器错误,还是仅通过实际启用 C++11 会产生编译器错误? (在许多情况下,这仍然不是默认设置)
  • @mkrieger1 这是一个很好的观点 - 您可能需要为此启用 C++11(或 C++14 或 C++17)模式。
  • @mkrieger1 较新的 GCC 和 trunk Clang 默认为 -std=gnu++14(“C++14 加上不​​符合标准的 GNU 扩展”模式)。 VS2017根本没有C++98或C++11模式。
【解决方案2】:

在我的 lapi 中,我正在使用 CodeBlocks 并获得输出

0x489944你好世界!

发生这种情况是因为 cout 是一个对象 ostream 类,并且当您执行类似的操作时

cout << " "<< endl << cout << "Hello world!" <<endl;

第一个 cout 正在控制台屏幕上打印,第二个 cout 被视为要与“hello world”一起打印的值,后者是第二个 cout 要打印的值。

所以基本上你从第二个cout 得到输出“Hello world”,并且你在 hello 之前得到 1 或其他数值,这是由第一个 cout 打印的,作为第二个 cout 的参考地址.

在您的情况下,控制台上将打印 1 作为 cout 的引用地址,这可能会因编译器而异。

【讨论】:

  • 我相信 1 来自布尔转换
  • 它看起来像在 C++03 中,coutoperator void*() const; 本质上是 return fail() ? NULL : this;。 C++11 移至explicit operator bool() const;。 1 不是“cout的引用地址”,您只是没有使用 C++11 或更高版本进行编译。
【解决方案3】:

对于大多数 &lt;&lt; 操作,cout &lt;&lt; x(其中 x 属于“大多数”类型)返回 cout 本身。

(这不是绝对规则,您可以定义一些operator &lt;&lt; 不正确的地方;但通常是这种情况)

所以cout &lt;&lt; " "&lt;&lt; endl &lt;&lt; cout 被解析为((cout &lt;&lt; " ") &lt;&lt; endl) &lt;&lt; cout

所以是一样的:

auto o1 = cout << " ";
auto o2 = o1 << endl;
auto o3 = o2 << cout;

所以第一个赋值(o1)输出一个空格并返回cout(实际上是对它的引用)。

(o2)的第二个赋值输出行尾,刷新缓冲区,返回cout

o3 的赋值计算 cout &lt;&lt; cout;

没有定义该运算符的重载。右边的cout转换成bool,净效果和cout &lt;&lt; true一样,输出1,返回cout

【讨论】:

    猜你喜欢
    • 2018-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 2015-12-04
    • 1970-01-01
    • 2017-07-30
    • 1970-01-01
    相关资源
    最近更新 更多