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

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

本文关键字:输出 添加 字符 缓冲区 是否 操纵 std ends      更新时间:2023-10-16

再次阅读C++入门书5ed,我有一个简单的问题:

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

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

#include <iostream>

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

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

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

  • 对我来说重要的是使用std::ends的第三行; 据说这个操纵器在输出缓冲区中插入了一个 Null 字符,但输出与其上方的行相同;哪个打印了不可读的尾随字符,我想std::ends没有在输出缓冲区中插入?!

这是输出:

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

谢谢。

std::ends是一个古老的操纵器,旨在用于现已弃用的数组 I/O 流,如std::strstreamstd::istrstreamstd::ostrstream。您很少(如果有的话)必须在实践中使用它。

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

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

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

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