gpt4 book ai didi

c - 如何正确解决指针对齐增加的问题?

转载 作者:太空宇宙 更新时间:2023-11-04 03:35:18 25 4
gpt4 key购买 nike

考虑以下结构:

typedef struct {
uint32_t foo;
uint32_t bar;
} first_struct_t;

typedef struct {
first_struct_t f;
uint8_t *p;
uint8_t buf[];
} second_struct_t;

但是,稍后在我的代码中,会发生以下分配:

typedef struct {
first_struct_t *f;
// ...
} some_struct;

int function_before_foo(some_struct *p) {
p->f = (second_struct_t *) malloc(sizeof(second_struct_t));
// ...
}

int function_foo(some_struct *p) {
second_struct_t *s = (second_struct_t *) p->f;
// ...
}

并且由于 -Wcast-align 而产生以下错误:

'second_struct_t *' increases required alignment from 4 to 8 [-Werror,-Wcast-align]
second_struct_t *s = (second_struct_t *) p->f;

一个解决方案是将其转换为 void *,但这似乎只能掩盖问题。最干净的解决方案是什么?

编辑:这只发生在 clang 而不是 GCC 上,不管这两个编译器都被赋予了 -Wcast-align 标志。

最佳答案

我假设当您使用 struct_second_t 时,您实际上是指 second_struct_t,否则您的代码无法编译。

问题是 some_struct 中的 f 是指向 first_struct_t 的指针,而不是指向 second_struct_t 的指针.

我应该补充一点,struct_second_t *s = (struct_second_t *) p->f; 中的转换隐藏了警告消息。一般来说,如果你必须将一个指针转换为另一个指针,你往往不会导致未定义的行为。这并不总是正确的,但却是一个很好的指导方针。

回应评论。

首先,对于 x86(32 位和 64 位)的 gcc,您似乎不会收到该警告,因为通用寄存器没有对齐要求,尽管对齐可以提高性能(有关更多信息,请参见 SO post)。至于为什么 clang 会发出该警告,可能是因为性能或者它们没有像 gcc 对 x86 那样的异常。

其次,您要完成的与 container_of 类似。 Linux 内核中的宏。 container_of 通常定义为:

#define container_of(ptr, type, member) ({                      \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})

在搜索中,我发现唯一可以解决您的问题的是 this commit to tup 更改了他们的 container_of 版本以包含对 void* 的强制转换。

基本上,我认为问题是当您知道 p->f 实际上指向 second_struct_t 时您的编译器并没有因此发出警告。因此,您可以不这样做,也可以强制转换为 void*

附加:

似乎 mozilla 也通过转换为 void* 解决了这个问题:

最后,我建议查看 container_of 并使用它,而不是依赖结构的第一个元素是另一个结构这一事实。这样你的代码更有弹性,如果其他人改变了结构成员的顺序,它仍然可以工作。您必须将 void* 添加到 container_of 以避免警告。请注意,在存在对齐问题的架构上,假设您始终正确地在子级和父级之间进行类型更改,则在运行时应该不会出现问题。

关于c - 如何正确解决指针对齐增加的问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33218873/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com