如何在避免 char 行为的同时将 uint8_t用于 I/O 流?

How do I use an uint8_t with I/O streams while avoiding the char behavior?

提问人:Maya 提问时间:10/19/2019 更新时间:10/19/2019 访问量:1235

问:

考虑这个简单的 C++ 程序:

#include <cstdint>
#include <iostream>

int main() {
    uint8_t var;
    std::cin >> var;
    std::cout << "var = " << var << '\n';
    if (var == 1) {
        std::cout << "var is 1\n";
    } else {
        std::cout << "var is not 1\n";
    }
}

运行它显示出一些令人惊讶的行为。当输入为 时,输出为1

var = 1
var is not 1

这显然是荒谬的!经过相当多的测试,我意识到发生了什么——这是在读写一个字符不过,这不是我想要的行为——我之所以使用,是因为我想要 eger 行为。在执行流 I/O 时,如何使uint8_t的行为与其他整数类型一样?或者,我应该使用哪种单字节类型uint8_tint

C++ IO 整数 IOstream

评论

1赞 NathanOliver 10/19/2019
如果您使用的是 C++17,请切换到使用 。然后,您可以重载输入和输出运算符以“做正确的事”std::byte
1赞 lakeweb 10/19/2019
uint8_t作为字符输入,因此其值为 31,而不是 1。
0赞 Maya 10/19/2019
@lakeweb读了这个问题。我已经知道了。我不是在问发生了什么,而是在问如何获得更合理的行为。
0赞 Brian Bi 10/19/2019
你不能。您必须读取一个,然后将其转换为 .unsigned intuint8_t
0赞 Maya 10/19/2019
@NathanOliver 谢谢!我主要将C++用于小型的一次性程序,所以这有点矫枉过正。我可能仍然会改用以避免将来被它咬伤。但是,有没有内置的东西真的是整数?std::byte

答:

3赞 bloody 10/19/2019 #1

您需要强制转换为:int

std::cout << "var = " << static_cast<int>(var) << '\n';

或更短(C 型):

std::cout << "var = " << (int)var << '\n';   //or:
std::cout << "var = " << int(var) << '\n';   //constructor-like

甚至更短(使用算术运算符提升到):int

std::cout << "var = " << +var << '\n';

评论

2赞 Borgleader 10/19/2019
虽然最后一个较短,但我认为它很聪明/令人惊讶,所以我个人建议不要这样做。
3赞 eerorika 10/19/2019 #2

在执行流 I/O 时,如何使uint8_t的行为与其他整数类型一样?

你不能。 显然你可以。

如果是 的别名,就像通常(可能总是)一样,则它是一种字符类型,标准流将其视为字符类型。std::uint8_tunsigned char

在插入到流之前,可以将其转换为非字符整数类型:

 std::cout << "var = " << static_cast<unsigned>(var) << '\n';

或者使用中间变量:

unsigned temp = var;
std::cout << "var = " << temp << '\n';

流提取仅适用于中间变量方法:

unsigned temp;
std::cin >> temp;
var = temp;

在相关的说明中,如果您希望输出变量的地址,则不起作用,因为它将被视为以 null 结尾的字符串......但事实并非如此,因此会导致未定义的行为。为此,您可以使用 .std::cout << &var;std::cout << static_cast<void*>(&var);

评论

0赞 Maya 10/19/2019
很公平。有等价物吗?cin
0赞 bloody 10/19/2019
unsigned temp = var;这是一种隐含的皈依,因此在惯用上更丑陋。在语法上也更笨重,如果与直接投射相比,这是毫无意义的。int