jga*_*lar 3 c c99 c-preprocessor
我一直在研究现有的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]
Run Code Online (Sandbox Code Playgroud)
大多数时候,这些警告是在将指针传递给函数的结构成员时生成的。例如:
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]
Run Code Online (Sandbox Code Playgroud)
有很多解决此问题的方法。立即想到的是memcpy()将相同类型的堆栈分配变量的值传递给该堆栈变量。
int bar(const int *val)
{ ... }
struct {
int a;
char b;
int c;
} __attribute__((packed)) foo;
// &foo.c is not aligned
bar(&foo.c)
Run Code Online (Sandbox Code Playgroud)
在此过程中,它将产生许多样板代码,我希望避免引入。
目前,我一直在考虑使用以下形式的宏
#define ALIGN_VALUE_PTR(val) (&((const typeof(val)) { val }))
bar(ALIGN_VALUE_PTR(foo.c));
Run Code Online (Sandbox Code Playgroud)
这适用于标量类型。但是,可以预见的是,如果val为a struct,则将不起作用。
int tmp;
memcpy(&tmp, &foo.c, sizeof(foo.c));
bar(&tmp)
Run Code Online (Sandbox Code Playgroud)
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 }))
| ^~~
Run Code Online (Sandbox Code Playgroud)
我想知道是否有人比我想出的更好。
#define ALIGN_VALUE_PTR(val) (((const typeof(val) []) { val }))
Run Code Online (Sandbox Code Playgroud)
您的原始版本不起作用的原因是由于微妙之处在于在初始化程序中如何处理大括号,以及复合文字始终至少需要至少一个大括号的事实。您可以将结构初始化为
struct s bar;
//...
struct s foo = bar;
Run Code Online (Sandbox Code Playgroud)
但您不能执行以下操作:
struct s foo = { bar };
Run Code Online (Sandbox Code Playgroud)
因为在花括号内,bar必须具有与而struct s不是第一个成员匹配的类型struct s。
使用数组(或结构;也有一些涉及免费结构的变体)使您可以匹配括号级别,以将所需的结构类型用作初始化程序。当然,数组形式从数组类型开始,并且仅通过衰减变成指针。如果要确保它始终是指针,请添加免费的+0或&*强制衰减。