-1

再次阅读 C++ Primer 5ed 我有一个简单的问题:

据说操纵器std::ends将空字符插入\0输出缓冲区,然后将其刷新。

所以我试图通过一个例子来理解它:

#include <iostream>


int main() {

    char sz[]{ 'H', 'e', 'l', 'l', 'o', '!' }; // no null-terminator character ('\0')
    std::cout << sz; // Hello!
    std::cout << sz << std::flush;
    std::cout << sz << std::ends;

}

在第一个输出行的上方,我在字符数组中附加了一些不可读的字符;好的,因为我没有\0sz.

  • 在第二行中,输出看起来像第一行,但会强制刷新缓冲区。

  • 第三行使用什么对我很重要std::ends;据说这个操纵器将一个 Null-Character 插入到输出缓冲区中,但输出与上面的行相同;哪个打印我猜std::ends没有插入\0输出缓冲区的不可读尾随字符?!

这是输出:

Hello!╠╠╠╠╠╠ظش↕♠L·6
Hello!╠╠╠╠╠╠ظش↕♠L·6Hello!╠╠╠╠╠╠ظش↕♠L·6

谢谢你。

4

1 回答 1

4

std::ends是一个古老的操纵器,旨在用于现已弃用的数组 I/O 流,如std::strstreamstd::istrstreamstd::ostrstream. 你很少会在实践中使用它。

您的代码中的问题是std::cout << sz << std::ends首先执行std::cout << sz将打印字符数组。字符数组的提取器重载旨在继续打印每个字符,直到找到空终止符。sz不会以 1 结束,因此提取器只会不断迭代数组的末尾,直到它在周围的内存中遇到一个随机的空字符。由此产生的结果称为未定义行为。编译器不再需要符合代码的逻辑,因此输出可能是无意义的垃圾,或者它可以以看起来像代码正在运行的方式打印它。未定义的行为意味着未定义。

添加<< std::ends不会以空值终止字符数组,它是在执行第一个表达式后执行的单独操作。

如果您想按原样打印字符数组,我建议您使用write

std::cout.write(sz, sizeof(sz));
于 2019-07-23T23:30:52.247 回答