以下代码不能在 C++20 中编译
#include <iostream>
#include <cstddef>
int main(){
std::byte b {65};
std::cout<<"byte: "<<b<<'\n';// Missing overload
}
Run Code Online (Sandbox Code Playgroud)
std::byte
C++17什么时候加入的,为什么没有对应的operator<<
重载打印呢?我也许可以理解不打印容器的选择,但为什么不std::byte
呢?它试图充当原始类型,我们甚至有 的重载std::string
,最近的std::string_view
,也许是最相关的 std::complex
,并且std::bitset
它本身可以被打印。
还有std::hex
类似的修饰符,所以默认打印 0-255 应该不是问题。
这只是疏忽吗?怎么样operator>>
,std::bitset
有它,它根本不是微不足道的。
编辑:发现甚至std::bitset
可以打印。
考虑unsigned char v
进行一系列按位运算并将结果存储回 的情况v
。在底层,它被整数提升一次,经历一系列操作,结果被截断并存储回v
。
然而std::byte v
,对于每个操作,操作数首先被提升为整数,进行操作,并且(中间)结果被截断并存储回某个std::byte
。这将是许多来回的提升和截断。这都是概念性的,但它会在实践中造成真正的开销吗?
// `mask` and `lshf` are of type `unsigned`
unsigned char v = ...;
v = (v & mask) << lshf; // one promotion at `&` and one truncation at `=`
Run Code Online (Sandbox Code Playgroud)
// `mask` and `lshf` are of type `std::byte` and `unsigned`
std::byte v = ...;
v = (v & mask) << lshf;
// It would be like
// byte(unsigned(byte(unsigned(v) & unsigned(mask))) << …
Run Code Online (Sandbox Code Playgroud) 我真的很喜欢std::byte
作为一种独特的类型,它实现了 C++ 语言定义中指定的字节概念。我不喜欢的是,现代 C++ 编译器将使用标准算法生成优化程度较低的代码。
在这里,我正在使用一个检查标头中前 4 个字节的函数,您可以在Godbolt上关注我的代码片段
bool func_bytes(const std::array<std::byte, 1024>& buf) {
constexpr std::array<std::byte, 4> header {
std::byte{0xDE}, std::byte{0xAD}, std::byte{0xBE}, std::byte{0xAF}
};
return std::equal(header.begin(), header.end(), buf.begin());
}
Run Code Online (Sandbox Code Playgroud)
这将在 x86-64 gcc trunk 上生成以下程序集
func_bytes(std::array<std::byte, 1024ul> const&):
cmp BYTE PTR [rdi], -34
jne .L5
cmp BYTE PTR [rdi+1], -83
jne .L5
cmp BYTE PTR [rdi+2], -66
jne .L5
cmp BYTE PTR [rdi+3], -81
sete al
ret
.L5:
xor eax, eax
ret
Run Code Online (Sandbox Code Playgroud)
如果我将 替换std::byte
为unsigned char …
std::byte
在 C++17 中定义为:
enum class byte : unsigned char {};
Run Code Online (Sandbox Code Playgroud)
我目前坚持使用 C++14,我想知道如果我在 C++14 中添加相同的定义(在某些非 std 命名空间中,以及运算符重载等),这个新类型会得到相同的结果吗?将“free-pass”别名化为unsigned char
或由于违反严格的别名规则而将自己设置为未定义的行为?
它似乎有效,但我想知道我是否应该选择它using byte = unsigned char;
,这会导致其他并发症(例如,我无法区分 byte 和uint8_t
)。
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
等作为“字节”的所有误解是很有用的。鼓励编辑。
我正在努力理解以下代码行:
if constexpr (std::is_same_v<T, bool>)
{
std::byte change = std::byte(static_cast<uint32_t>(in) << m_addr[1]);
std::byte mask = ~std::byte(1u << m_addr[1]);
dataBlock[m_addr[0]] = (dataBlock[m_addr[0]] & mask) | change;
}
Run Code Online (Sandbox Code Playgroud)
其中dataBlock
是 a std::vector<std::byte>
,T
是in
的类型,并且m_addr
是 a std::array<std::byte, 2>
。这会进行位移位以便将 bool 值存储在字节内。我的问题是关于声明中的第一行if
。对于此示例,我将使用in = 1
和m_addr[1] = 3
。
根据我的理解,static_cast<uint32_t>(in)
创建了一个uint32_t
给定的00000000,00000000,00000000,00000001
; 左移运算符将其转换为00000000,00000000,00000000,00001000
,然后将其转换为std::byte
。
如何std::byte
选择存储的字节?我假设它存储 LSB,所以00001000
,但我找不到任何参考资料来证实这一点。它可以存储MSB(所以00000000
)吗?如果是,我怎样才能使下面的实现平台无关?
根据标准参考,std::is_enum_v
枚举类型的计算结果为 true,否则为 false。枚举类型以枚举键开头,即枚举、枚举类或枚举结构之一。
编写了以下测试程序:
#include <type_traits>
#include <iostream>
using to_examine = std::byte;
enum class Foo {
ONE,
TWO
};
int main() {
if constexpr (std::is_enum_v<std::byte>) {
std::cout << "byte counts as enum" << std::endl;
}
if constexpr(std::is_enum_v<int>) {
std::cout << "int counts as enum" << std::endl;
}
if constexpr(std::is_enum_v<Foo>) {
std::cout << "scoped enum counts as enum" << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
打印出以下内容:
byte counts as enum
scoped enum counts as enum
Run Code Online (Sandbox Code Playgroud)
我正在使用 clang15 和 …
我知道我可以使用reinterpret_cast
,但是我不能从 char 转换为像 std::byte 这样的“通用”类型似乎很奇怪。这只是不幸的错误/限制,还是有原因?
示例:
int main(){
std::string s{"abc"};
std::byte* ptr = static_cast<std::byte*>(s.data());
}
Run Code Online (Sandbox Code Playgroud) 类型由位std::byte
组成CHAR_BIT
,并且可以多于8位。
那么,如何在 C++ 中声明真正的八位字节?