std::cout << static_cast<uint8_t>(65);
它将输出:
A
这是数字65的ASCII等效值。
这是因为uint8_t
被简单地定义为:
typedef unsigned char uint8_t;
这种行为是标准吗?
是否有更好的方法来定义
uint8_t
,以保证它被处理为数字而不是字符?
我无法理解这种逻辑:如果我想打印一个uint8_t
变量的值,它会作为字符打印。
P.S. 我正在使用MSVS 2013。
std::cout << static_cast<uint8_t>(65);
它将输出:
A
这是数字65的ASCII等效值。
这是因为uint8_t
被简单地定义为:
typedef unsigned char uint8_t;
这种行为是标准吗?
是否有更好的方法来定义uint8_t
,以保证它被处理为数字而不是字符?
我无法理解这种逻辑:如果我想打印一个uint8_t
变量的值,它会作为字符打印。
P.S. 我正在使用MSVS 2013。
uint8_t
是 unsigned char
的 typedef,则始终会将字符打印为 std::ostream
具有 unsigned char
的重载,并输出变量内容作为字符。uint8_t
以保证其被视为数字而非字符。要做到这一点,C++委员会必须引入一个新的基本类型。目前,唯一具有等于1的sizeof()
的类型是char
、signed char
和unsigned char
。他们可能会使用一个bool
,但是bool
不一定要有大小为1的大小,然后你仍然面临同样的问题。int main()
{
bool foo = 42;
std::cout << foo << '\n';
}
将打印1,而不是
42
,因为任何非零值都为true,并且默认情况下true将打印为1
。
我不是说这不能完成,但对于可以使用强制转换或函数处理的事情而言,这需要大量工作。
C++17引入了std::byte
,它被定义为enum class byte:unsigned char {};
。 因此,它将是一个字节宽度,但它不是字符类型。 不幸的是,由于它是一个enum class
,它自带限制。 对它进行了按位运算符的定义,但没有内置的流运算符来处理它,因此您需要定义自己的流运算符来输入和输出它。 这意味着您仍在进行转换,但至少您不会与unsigned char
的内置运算符冲突。 那会得到像这样的东西
std::ostream& operator <<(std::ostream& os, std::byte b)
{
return os << std::to_integer<unsigned int>(b);
}
std::istream& operator <<(std::istream& is, std::byte& b)
{
unsigned int temp;
is >> temp;
b = std::byte{b};
return is;
}
int main()
{
std::byte foo{10};
std::cout << foo;
}
在评论中有一些错误信息,因此我会发表回答。
uint8_t
可能是 char
或 unsigned char
的 typedef。它也可能是扩展整数类型(因此不是字符类型)。
编译器可能提供标准所需的最小整数类型集之外的其他整数类型(例如 short
、int
、long
等)。例如,某些编译器提供了 128 位整数类型。
这也不会“与 C 冲突”,因为 C 和 C++ 都允许扩展整数类型。
因此,您的代码必须考虑这两种可能性。评论中使用一元 +
的建议是可行的。
个人认为,如果标准要求 uint8_t
不是字符类型,则更有意义,因为您注意到的行为是不直观的。
这是一种间接的标准行为,因为ostream
有一个针对unsigned char
的重载,而在您的系统中unsigned char
是相同类型uint8_t
的typedef。
§27.7.3.1 [output.streams.ostream]表明:
template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, unsigned char);
我在标准中找不到明确说明uint8_t
和unsigned char
需要相同的地方,但是,在几乎所有实现中,它们都占据1个字节是合理的。
std::cout << std::boolalpha << std::is_same<uint8_t, unsigned char>::value << std::endl; // prints true
uint8_t a = 65;
std::cout << static_cast<uint16_t>(a) << std::endl; // prints 65
uint8_t
可以是扩展整数类型。 - M.Muint8_t
底层类型必须是什么的东西,因为uint8_t
可能甚至不存在。 - NathanOliveruint16_t
在一个具有 16 位 char
的系统上可能会遇到相同的问题。(尽管这种情况很少见) - M.Muint8_t
的人)只是不幸地选择了unsigned char
作为其typedef,并且它可能不会很快改变,因为这是一个合理的实现。 - AndyG
uint8_t
作为小的无符号整数使用,在输出之前需要进行类型转换。例如:static_cast<uint32_t>(some_uint8_t_variable)
。 - Some programmer dudechar
变体的原始类型。是的,C++可以添加新类型,但这将与这些typedef起源的C冲突。 - Pete Beckerstd::cout << +static_cast<uint8_t>(65);
会实现你想要的功能。 - Pete Becker