#define struct union和#define else仍然编译任何C程序吗?

#define struct union和#define else仍然编译任何C程序吗?,c,struct,c-preprocessor,language-lawyer,unions,C,Struct,C Preprocessor,Language Lawyer,Unions,有人在演示文稿中声称,如果您添加 #define struct union #define else 在任何有效的C程序开始时,该程序仍将编译。这似乎是一个大胆的主张。你有什么反例可以证明那个家伙错了吗?我找到了一个反例(C99): for(int i=0;i2) dousmth(); 否则如果(i

有人在演示文稿中声称,如果您添加

#define struct union
#define else

在任何有效的C程序开始时,该程序仍将编译。这似乎是一个大胆的主张。你有什么反例可以证明那个家伙错了吗?

我找到了一个反例(C99):

for(int i=0;i<5;++i)
如果(i>2)
dousmth();
否则如果(i<4)
你还有别的事吗;
这个变量不可编译,因为如果您定义else,变量
i
将超出范围。但这并不涉及定义结构联合(define struct union)这件事。还有其他想法吗?

如果
STATIC\u ASSERT()
是您最喜欢的静态断言宏,那么:

struct {int a, b, c, d;} x;
//...
STATIC_ASSERT(sizeof x == 4 * sizeof(int));
如果您有
#define struct union
,则不会编译

#define else 42
如果在其前面添加
#define else
,则无效(因此可能无法编译)

当前定义为类似于宏的对象的标识符不得由 另一个#define preprocessing指令,除非第二个定义是类似对象的宏 定义和两个替换列表是相同的

(ISO/IEC 9899-1999,§6.10.3,2)


C2078:太多的初始值设定者

另一个与
else
声明相反的例子,我认为这可以追溯到K&R C:

void do_something() {}
do
  if (1) do_something(); else do_something();
while(0);
do
后面必须紧跟一条语句<代码>如果(条件)语句;else语句构成一条语句,但删除
else
将导致它成为两条语句

对于结构与联合,给定

typedef union {int x, y; } t;
t a[3] = {1,2,3};

我认为编译器需要将3存储到
a[2].x
(也称为
a[2].y
)中,并且没有地方存储任何附加的初始化值。如果
t
是一个结构,那么3将进入
a[1].x
,并且还有空间再容纳三个值。

用于(int i=0;…
C99,还是只是一个gcc/msvc扩展?事实是“else”将两条语句合并为一条语句是一个很好的观察结果;我根据相同的原则发布了一个反例,追溯到K&R C。C 2011标准中对“struct”或“union”的每一次引用都对称地使用了这两条语句。(6.7.2中有一条引用只使用“struct”而不使用“union”),但我认为它指的是两者,如6.7.2.1所示。)此外,它们共享相同的标记名空间,因此不能通过标记行为来区分它们。因此,没有语法差异。用“union”替换“struct”会使程序失败必须依赖于语义,而不是语法,例如某些答案中提出的大小问题。一个简单的反例是,如果代码已经包含对任一宏的不同定义。@undur_gongor:这应该是答案。除非
4*sizeof(int)
恰好是给定系统的精确对齐要求。union将获得填充字节,这将很好地编译。@Lundin:“给定系统的精确对齐要求”是什么对于
int
尚未满足的
int
的结构或联合,没有特殊的对齐要求。正常的C实现不会向结构或只包含四个
int
的联合添加填充。(尽管C标准允许实现无理由地添加填充,正如我在其他地方指出的那样。)@EricPostDischil“对于int尚未满足的int的结构或并集,没有特殊的对齐要求”。在实践中适用于市场上的所有主流体系结构,但在理论上不正确。例如:如果有一个仅由int组成的并集,int为16位,给定系统的对齐要求为8字节。那么当并集定义为struct时,此代码将编译。我知道这是一个奇怪的理论案例,但严格来说是允许的C标准。@Lundin:您尚未定义“给定系统的对齐要求”。如果
int
为16位,则根据标准对数组和
sizeof
的要求,n
int
数组的大小必须为n•16位。这意味着系统必须能够以16位的奇数倍访问
int
对象;系统中不要求所有对象都与mu对齐ltiples 8字节。联合必须遵守但对象不需要的对齐要求是什么?@EricPostpischil对齐要求在硬件中,而不是在C标准中,因此它是实现定义的……该标准只要求在相邻内存中分配数组的项。没有要求标准中的对齐要求CPU必须能够直接访问未对齐的数组项。编译器可以在CPU无法访问的系统上自由实施任何类型的技巧来访问这样的数组成员。否则,在CPU无法执行未对齐访问的系统上不可能有任何类型的数组ss.好的,很好,但我正在寻找一种方法来利用已经添加的
#define
。@webuster:是的,我理解。这就是为什么我最初添加它只是作为注释。有趣。我见过的所有编译器都将此视为警告,而不是错误(大概是为了向后兼容)除非你特别添加了一个开关,如
-Werror
。我似乎记得旧的编译器甚至不会给你一个警告。@约瑟夫·昆西:你说得对。我重新措辞了一点。谢谢。@JosephQuinsey:不给警告的编译器不符合C标准;6.10.3是一个约束子句,5.1.1.3需要任何约束冲突的诊断消息。回答很好。您可以将其简化为一行:
struct{int a,b;}x={0,0};
。此外,我的gcc版本似乎总是编译此消息,尽管有警告,但u
void do_something() {}
do
  if (1) do_something(); else do_something();
while(0);
typedef union {int x, y; } t;
t a[3] = {1,2,3};