输出操纵器 std::ends 是否将空字符添加到输出缓冲区?

Does the output manipulator std::ends add a Null-character to the output buffer?

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

据说操纵器std::ends向输出缓冲区插入一个空字符[=14=]然后刷新它。

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

#include <iostream>


int main() {

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

}

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

添加空字符 [=14=]

这是输出:

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

谢谢。

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

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

添加 << std::ends 不会 null-terminate 字符数组,它是一个单独的操作 第一个表达式执行后执行。

如果您想打印字符数组 as-is 我建议使用 write:

std::cout.write(sz, sizeof(sz));