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

问题描述 投票:0回答:1

我需要使用打包结构来解析传入的数据。我还有一个 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;
}

clang:https://godbolt.org/z/eWfaqb3a3

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

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

c++ gcc clang std option-type
1个回答
3
投票

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

因此对于 Clang 来说,为未对齐的

int&

创建一个

t.b
是完全可以的,因为 CPU 会透明地处理可能导致的未对齐访问。
另一方面,对于 GCC,从 

int&

创建

t.b
会带来代码访问它并导致陷阱的风险。采用
int&
的函数的合约规定
int
必须对齐。所以编译器失败,因为合同无法得到满足。
但是,如果您编写 

(decltype(t.b)) t.b;

,您将创建要使用的

t.b
的副本,从而避免未对齐的问题,因为编译器知道如何复制未对齐的
uint32_t
您可以指定编译器标志来更改有关未对齐访问的默认假设。允许 GCC 应该使代码编译,但假设您的 ARM CPU 将配置为允许所述未对齐访问。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.