我一直在研究现有的 C99 代码库,该代码库到处都使用指向打包结构成员的指针。这会导致表单警告。
my_file.c:xxx:yy: error: taking address of packed member of 'struct some_packed_struct' may result in an unaligned pointer value [-Werror=address-of-packed-member]
大多数情况下,这些警告是在将指向结构成员的指针传递给函数时生成的。例如:
int bar(const int *val)
{ ... }
struct {
int a;
char b;
int c;
} __attribute__((packed)) foo;
// &foo.c is not aligned
bar(&foo.c)
这个问题有很多不同的解决方案。立即想到的是 memcpy()
将值赋给相同类型的堆栈分配变量,并将指针传递给该堆栈变量。
int tmp;
memcpy(&tmp, &foo.c, sizeof(foo.c));
bar(&tmp)
虽然这可行,但会产生大量样板代码,我宁愿避免引入。
目前,我一直在考虑使用以下形式的宏
#define ALIGN_VALUE_PTR(val) (&((const typeof(val)) { val }))
bar(ALIGN_VALUE_PTR(foo.c));
这适用于标量类型。然而,可以预见的是,如果 val
是一个 struct
,这将不起作用。
struct inner {
int c, d;
};
struct outer {
int a, b;
struct inner inner;
};
void print_inner_field(const struct inner *inner)
{
printf("value is %d\n", inner->c);
}
struct outer outer;
print_inner_field(ALIGN_VALUE_PTR(outer.inner));
lol.c:28:30: error: incompatible types when initializing type ‘int’ using type ‘struct inner’
28 | print_inner(ALIGN_VALUE_PTR(foo.inner));
| ^~~
lol.c:3:55: note: in definition of macro ‘ALIGN_VALUE_PTR’
3 | #define ALIGN_VALUE_PTR(val) (&((const typeof(val)) { val }))
| ^~~
我想知道是否有人有比我想出的更好的主意。
最佳答案
#define ALIGN_VALUE_PTR(val) (((const typeof(val) []) { val }))
您的原始版本不起作用的原因是因为初始化器中大括号的处理方式很微妙,而且复合文字总是需要至少一级大括号。您可以将结构初始化为
struct s bar;
//...
struct s foo = bar;
但你不能这样做:
struct s foo = { bar };
因为,在大括号内,bar
必须具有匹配 struct s
的第一个成员的类型, 不是 struct s
.
使用数组(或结构;也有涉及无偿结构的变体)允许您匹配大括号级别以使用您想要的结构类型作为初始值设定项。数组形式当然以数组类型开始,并且仅通过衰减成为指针。如果您想确保它始终是一个指针,请添加一个无偿的 +0
或 &*
强制腐烂。
关于c - 宏如何返回指向未对齐值的对齐指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57936757/