提问人:nikolaj 提问时间:6/24/2022 更新时间:6/24/2022 访问量:257
std::optional 和打包结构成员的 gcc 问题
gcc problem with std::optional and packed struct member
问:
我需要使用打包的结构来解析传入的数据。我还有一个 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
我知道打包结构的一般问题。由于我的目标是具有 x86-64 的嵌入式设备,并且正在解析的数据来自工业标准总线,因此我相信我是安全的。
答:
这是 clang 和 gcc 如何假设配置了 ARM cpu 的问题。
ARM CPU 有一点说明未对齐的访问是否应导致处理器陷阱,或者由 cpu 使用较慢的访问方法透明地处理。Clang 默认为 CPU 允许未对齐的访问,而 gcc 默认为 CPU 捕获未对齐的访问。
因此,对于 clang 来说,为未对齐创建 a 是完全可以的,因为 CPU 将处理可能导致的未对齐访问。int&
t.b
另一方面,对于 gcc,创建一个 from risk 代码,访问它并造成陷阱。职能的合同规定必须保持一致。所以编译器失败是因为无法满足约定。int&
t.b
int&
int
但是,如果您编写,则会创建一个要使用的副本,这样可以避免未对齐的问题,因为编译器知道如何复制未对齐的 .(decltype(t.b)) t.b;
t.b
uint32_t
您可以指定编译器标志来更改有关未对齐访问的默认假设。允许 gcc 使用它应该使代码编译,但假设您的 ARM cpu 将配置为允许上述未对齐的访问。
评论
I need to
你为什么需要?只需从传入数据中提取字节并移动到适当的位置即可。没有必要使用数据包结构,你选择使用它,我说根本不使用它,要可移植并自己编写代码。