将积分类型的数组作为另一个不相关的积分类型的阵列进行访问的安全且符合标准的方法

The safe and standard-compliant way of accessing array of integral type as an array of another unrelated integral type?

本文关键字:类型 安全 访问 方法 标准 不相关 数组 另一个 阵列      更新时间:2023-10-16

以下是我需要做的。我相信这对许多C++开发人员来说是一项常规且可识别的编码任务:

void processAsUint16(const char* memory, size_t size) {
auto uint16_ptr = (const uint16_t*)memory;
for (size_t i = 0, n = size/sizeof(uint16_t); i < n; ++i) {
std::cout << uint16_ptr[i]; // Some processing of the other unrelated type
}
}

问题:我正在使用一个集成了clang静态代码分析的IDE进行开发,我尝试过的每一种类型转换方法,除了memcpy(我不想使用它(之外,要么都不鼓励,要么都非常不鼓励。例如,reinterpret_cast只是被CPP核心指南所禁止。不鼓励使用C型铸造。此处不能使用static_cast

避免类型别名问题和其他未定义行为的正确方法是什么?

避免类型别名问题和其他未定义行为的正确方法是什么?

您使用memcpy:

void processAsUint16(const char* memory, size_t size) {
for (size_t i = 0; i < size; i += sizeof(uint16_t)) {
uint16_t x;
memcpy(&x, memory + i, sizeof(x));
// do something with x
}
}

uint16_t通常是可复制的,所以这很好。

或者,在C++20中,使用std::bit_cast(它必须首先通过一个数组(:

void processAsUint16(const char* memory, size_t size) {
for (size_t i = 0; i < size; i += sizeof(uint16_t)) {
alignas(uint16_t) char buf[sizeof(uint16_t)];
memcpy(buf, memory + i, sizeof(buf));
auto x = std::bit_cast<uint16_t>(buf);
// do something with x
}
}

实际上,如果只使用reinterpret_cast,编译器将"做正确的事情",即使它是未定义的行为。也许像std::bless这样的东西会给我们一个更直接、非复制的机制,但在那之前。。。

我的偏好是将char数组视为按定义顺序排列的八位字节序列。如果根据目标体系结构的不同,这显然是不起作用的,但在实践中,像这样的内存缓冲区通常来自文件或网络连接。

void processAsUint16(const char* memory, size_t size) {
for (size_t i = 0; i < size; i += 2) {
const unsigned char lo = memory[i];
const unsigned char hi = memory[i+1];
const uint16_t x = lo + hi*256;  // or "lo | hi << 8"
// do something with x
}
}

请注意,我们在这里不使用sizeof(uint16_t)memory是一个八位字节序列,所以即使CHAR_BITS是16,也需要两个字符来容纳一个uint16_t

如果memory可以声明为unsigned char,那么这可以稍微干净一点——不需要定义lohi