c - 宏如何返回指向未对齐值的对齐指针?

标签 c c-preprocessor c99

我一直在研究现有的 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/

相关文章:

c - 如何构建你的c程序?

c - 为什么#if 0 与#if (1 > 1)?

objective-c - Xcode:在另一个项目使用的一个项目中定义预处理器宏

c - 是否可以在 C99 中创建 "anonymous"初始化程序?

c - 为什么 SUCCEEDED 宏中有这么多括号?

c - 从文本文件中读取指令

Cuda 2D内存分配和复制问题

c - #define 在 header 中定义的变量未由代码设置

C99, "Despite the name, a non-directive is a preprocessing directive."