c++ - gcc std::可选和打包结构成员的问题

标签 c++ gcc clang std option-type

我需要使用打包结构来解析传入数据。我还有一个 std::Optional 值,我想将其分配给结构成员之一的值。然而,它失败了。我想我理解这个问题,基本上引用与内存宽度不对齐的变量可能是一件坏事。

该代码示例使用 clang 14 进行编译,但不能使用 gcc 12 进行编译。这是错误还是“功能”?

#include <cstdint>
#include <optional>

struct Data {
    uint8_t a{};
    uint32_t b{};
} __attribute__((packed));

int main() {
    Data t;
    std::optional<uint32_t> val{};
    val = t.b;  // <<< this failes
    val = (decltype(t.b)) t.b;
}

铿锵:https://godbolt.org/z/eWfaqb3a3

海湾合作委员会:https://godbolt.org/z/or1W5MbdG

我知道 general problems具有打包结构。由于我的目标是具有 x86-64 的嵌入式设备,并且正在解析的数据来自工业标准总线,因此我相信我是安全的。

最佳答案

这是 clang 和 gcc 如何假设 ARM cpu 配置的问题。

ARM cpu 有一个位,表示未对齐的访问是否会导致处理器陷阱,或者由 cpu 使用较慢的访问方法透明地处理。 Clang 默认 CPU 允许未对齐访问,而 gcc 默认 CPU 捕获未对齐访问。

因此,对于 clang 来说,为未对齐的 t.b 创建一个 int& 是完全可以的,因为 CPU 会透明地处理可能导致的未对齐访问。

另一方面,对于 gcc,从 t.b 创建 int& 存在代码访问它并导致陷阱的风险。采用 int& 的函数契约规定 int 必须对齐。因此编译器失败,因为契约(Contract)无法得到满足。

但是如果你写 (decltype(t.b)) t.b; 你会创建一个要使用的 t.b 的拷贝,这样就可以避免未对齐的问题,因为编译器知道如何复制未对齐的 uint32_t

您可以指定编译器标志来更改有关未对齐访问的默认假设。允许 gcc 应该会使代码编译,但假设您的 ARM cpu 将配置为允许所述未对齐访问。

关于c++ - gcc std::可选和打包结构成员的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72740619/

相关文章:

c++ - 使用 Clang 的 scan-build 和 scons 和 C++11

捕获列表中的 C++ lambda 复制值

c++ - 具有外部错误的模板特化

c - 为什么在 glibc 中使用 crypt 会导致编译器警告?

C: for loop int 初始声明

使用共享库 undefined symbol 的 Linux 共享库

c - flex 的链接器错误

c++ - QMessageBox使用快捷键多次打开

c++ - 在 C++ 中的二进制文件中存储可变大小结构的 vector

c - 内存布局黑客