Jan*_*tke 4 c++ byte c++17 std-byte
C++ 有很多类型模糊地描述相同的事物。假设我们正在针对一个字节为 8 位的架构进行编译,则以下所有类型都大致相似:
std::byte
std::uint8_t
std::bitset<8>
unsigned char
(8 位)char
(8 位)如果一个字节是 8 位,那么所有这些类型或多或少可以互换吗?如果没有,什么时候需要使用一个而不是另一个?
我经常在 Stack Overflow 上看到诸如将十六进制字符串转换为字节数组之类的问题,其中有人使用std::uint8_t
、char
和unsigned char
其他类型来表示“字节”。这只是风格偏好的问题吗?
注意:此问答旨在成为社区常见问题解答,鼓励进行编辑。std::byte
尽管 C++17 已经引入了这似乎使得选择变得显而易见,但何时使用“字节”的类型以及为什么的问题始终出现。std::bitset
提供一个常见问题解答来解决有关、std::uint8_t
等作为“字节”的所有误解是很有用的。鼓励编辑。
对于 8 位架构,所有列出的类型都隐约相似,因为它们都对 8 位的东西进行建模。然而,用例本质上是不同的,并且只有其中一些类型保证有特殊属性,使它们可以用作字节类型。
\n类型 | 定义 | 目的 |
---|---|---|
std::byte | enum class byte : unsigned char {}; | 规范字节类型 \xe2\x9c\x94\xef\xb8\x8f 所有特殊属性 |
unsigned char | 基本型 | 字符/旧字节类型/小型算术类型 \xe2\x9c\x94\xef\xb8\x8f 所有特殊属性 |
signed char | 基本型 | 字符/小算术类型 \xe2\x9d\x8c 无特殊属性 |
char | 基本类型signed char , 与或相同的基础类型unsigned char | 一个字符 \xe2\x9a\xa0\xef\xb8\x8f 只有一些特殊属性 |
char8_t | 基本类型与 底层类型 unsigned char | UTF-8 字符 \xe2\x9d\x8c 无特殊属性 |
std::uint8_t | typedef unsigned char uint8_t; (这并不能保证,只是最 常见的实现。) | 8 位无符号算术 \xe2\x9a\xa0\xef\xb8\x8f 不保证特殊属性 |
std::bitset<8> | template <std::size_t N> class bitset; | 8 位组;可能比 8 位宽 \xe2\x9d\x8c 无特殊属性 |
请参阅问题末尾的附录,了解所有这些特殊属性(按类型)的列表。
\nstd::byte
(C++17)这是C++ 中的规范字节类型。每当你不得不问自己这个问题“我应该使用哪种类型来表示这些字节?” ,std::byte
就是答案。
请注意,这std::byte
是非常特殊的,因为有许多放宽允许您以其他未定义的方式使用该类型。例如,严格的别名规则对于std::byte
( [basic.lval] p11 ) 来说是宽松的,这意味着您可以将任何对象作为 s 数组进行检查std::byte
。
大多数其他类型不具有这些特殊功能,并且尝试将它们用作字节将是未定义的行为。
\n与原始内存操作一样std::byte
,许多较旧的 API(例如<iostream>
库)早于它,并且不是围绕它设计的。\n该类型也有些笨重(例如,my_byte == 0
不可能)。\n不要尝试强制使用它与不是为std::byte
.
另请参阅:C++ 中是否有“字节”数据类型?, std::byte 的用途是什么?,\n P0298 - 字节类型定义*
\nunsigned char
这是 C++17 之前最接近“字节”的东西。\nunsigned char
具有 a 所具有的所有特殊属性std::byte
。
然而,这个名字非常令人困惑,并且在某些上下文中它也被视为一个字符。例如,std::ostream::operator<<
将其打印为 ASCII 字符,而不是打印其数值。另外,用 进行算术运算unsigned char
会将其提升到int
任何操作之前,这对于“字节”来说似乎不合适。
总而言之,它是一种软弱无力的类型,同时又是字节、字符和算术类型。更喜欢std::byte
、char
、std::uint8_t
、 或。std::uint_least8_t
另请参阅:如何在需要旧式 unsigned char 的地方使用新的 std::byte 类型?
\nsigned char
签名对应的 也unsigned char
同样令人困惑。它几乎没有std::byte
和 所unsigned char
具有的特殊属性,并且是算术类型和字符类型的奇怪组合。也应该避免这种情况。
一个更好的选择是std::int_least8_t
它也是带符号的,并且也保证至少 8 位宽,但它没有作为字符的奇怪含义。
另请参阅:signed / unsigned char 之间的区别
\nchar
signed char
这是一个不同的类型,与或具有相同的基础类型。\n它具有和unsigned char
的大部分(但不是全部)特殊属性。\n例如,与 不同,它不提供存储 ( [intro.object] p3 )在 a 中创建的对象。unsigned char
std::byte
unsigned char
char[]
char
应该用于顾名思义:一个字符。
另请参见:char!=(signed char)、char!=(unsigned char)
\nchar8_t
(C++20)最初有一些关于此类型具有类似于 的特殊属性的讨论char
,但最终没有。\n它的基础类型是unsigned char
,但与 不同std::byte
,这并不意味着它继承了它的任何属性。
它应该用作 UTF-8 字符,可能在 UTF-8 编码的字符串中。
\nstd::uint8_t
(C++11)这种类型是从 C 开始的设计错误。\n虽然不能保证这一点,但它通常作为类型别名实现,例如
\ntypedef unsigned char uint8_t;\n
Run Code Online (Sandbox Code Playgroud)\n这意味着它具有unsigned char
实际中具有的特殊属性(因为所有编译器都这样实现它),但标准并不能保证这些。\n它可以为所有其他类型别名的事实也可能使其对性能产生不利影响,与它是唯一类型的别名相比。
需要注意的一件事是,C++ 中的字节不能保证为 8 位。\n许多人使用它是因为它提供了真正8 位std::uint8_t
的安全性。\n但是,它是可选的,并且在以下平台上不存在:一个字节比 8 位宽,因此它的可移植性并不比:std::uint8_t
#include <climits>\nstatic_assert(CHAR_BIT == 8); // ... and use unsigned char or char as a byte type\n
Run Code Online (Sandbox Code Playgroud)\n对于更可移植的 8 位算术类型,有std::uint_fast8_t
和std::uint_fast8_t
,它们保证存在,但可能比 8 位宽。
注意std::uint8_t
,、、std::uint_least8_t
和std::uint_fast8_t
可能全部提升为int
, 就像unsigned char
。
另请参阅:uint8_t 与 unsigned char,哪些平台有除 8 位字符之外的其他内容?
\nstd::bitset<8>
这是距离“字节”类型最远的类型。\n它对位序列或一组数字进行建模,具体取决于视角。
\nAstd:bitset<8>
至少与int
大多数实现中一样大,因此它甚至不是 8 位大。仅将此类型用于其名称所示的用途:一组位。它不是一个字节。
std::byte
是唯一模拟字节的类型,仅此而已。只要有可能,就应优先将其作为字节类型。\n所有其他类型要么缺少关键属性,要么具有与字节完全不同的用途。
std::byte
普通字符类型的特殊属性部分 | 受影响的类型 | 特殊属性 |
---|---|---|
[介绍对象] p3 | unsigned char[] ,std::byte[] | 数组为放置在其中的对象提供存储 |
[介绍对象] p13 | unsigned char[] ,std::byte[] | 数组在其生命周期开始时隐式地在内部创建对象 |
[基础生活] p6.4 | 简历 char* 、简历 unsigned char* 、简历 std::byte* | static_cast 允许存在指向生命周期之外的对象的指针 |
[基本信息] | 无符号普通字符类型,std::byte | 初始化和分配时允许不确定的结果 |
[基本.类型.一般] p2 | char[] , unsigned char[] ,std::byte[] | 可简单复制的对象可以通过数组传输其值 |
[基本.lval] p11.3 | char , unsigned char ,std::byte | 宽松的严格别名 |
[expr.new] p16 | char[] , unsigned char[] ,std::byte[] | 新表达式中更严格的对齐 |
[位.cast] p2 | 无符号普通字符类型,std::byte | 允许不确定的结果std::bit_cast |
注意:尚不清楚无符号普通字符类型的实际含义。请参阅社论第 5070 期。
\n 归档时间: |
|
查看次数: |
933 次 |
最近记录: |