为什么 gcc 会意外地剥离 __attribute__(__packed__)?

why does gcc unexpectedly strip __attribute__(__packed__)?

预处理器在 -U__GNUC__ 已指定且至少有 1 个 #include 指令? 这对我来说似乎是令人惊讶的行为。这是一个例子:

$ cat foo.c
#include <limits.h>

struct S {
       int a;
} __attribute__((__packed__));
$ gcc -E -U__GNUC__ foo.c | tail -3
struct S {
       int a;
} ;

但是如果我删除#include 指令(或者如果我删除 -U__GNUC__)然后 属性不会被预处理器剥离,这就是我 期待发生。

$ cat foo2.c
struct S {
       int a;
} __attribute__((__packed__));
$ gcc -U__GNUC__ -E foo2.c
# 1 "foo2.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "foo2.c"

struct S {
        int a;
} __attribute__((__packed__));

这是一个 gcc 错误还是有关于此行为的文档?

在我的平台标准 headers 上间接包含 /usr/include/argp.h。在 argp.h 它说

#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later.  */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
#  define __attribute__(Spec) /* empty */
# endif
...
#endif

即对于 __GNUC__ 的低值和 __STRICT_ANSI__ 模式 __attribute__ 是 pre-defined 作为空宏。通过取消定义 __GNUC__,您可以使它在 #if 上下文中表现得像 0。因此,上面的代码将 __attribute__ 变成了一个空宏。