6.2.5p28提到
...所有指向结构类型的指针都应具有相同的指针 彼此之间的表示和对齐要求。所有指针 联合类型应具有相同的表示形式和对齐方式 彼此需求。指向其他类型的指针不必具有 相同的表示或对齐要求。
我相信正是这一段允许使用以下代码:
TAG x;
void take(TAG x* X) { (void)X; }
int main()
{
TAG x *xp = 0;
take(xp);
}
在TAG
被定义为扩展为struct
或union
关键字的宏时进行编译。
但是,它也是compiles (tcc, gcc, clang) when TAG
is defined as a macro expanding to the enum
keyword。
鉴于上述情况,用enum
代替TAG
符合C的代码吗?为什么或为什么不呢?
答案 0 :(得分:3)
这是您在评论中提供的链接中的代码:
#define TAG enum
TAG x;
void take(TAG x* X) { (void)X; }
int main() {
TAG x *xp = 0;
take(xp);
};
(名称“ TAG”具有误导性。标签是标识符;例如,在enum foo {a, b, c}
中,标签是foo
。)
这是无效的。当我使用gcc -std=c11 -pedantic-errors
进行编译时,我得到:
c.c:2:5: error: ISO C forbids forward references to 'enum' types [-Wpedantic]
TAG x;
^
c.c:4:15: error: ISO C forbids forward references to 'enum' types [-Wpedantic]
void take(TAG x* X) { (void)X; }
^
c.c: In function 'main':
c.c:7:7: error: ISO C forbids forward references to 'enum' types [-Wpedantic]
TAG x *xp = 0;
^
c.c: At top level:
c.c:9:2: error: ISO C does not allow extra ';' outside of a function [-Wpedantic]
};
^
由于允许向前引用struct
类型,所以所有指向结构的指针都必须具有相同的表示形式,因为编译器在看到指针类型时可能未看到完整的结构定义。
union
类型也是如此。对于enum
类型, not 相同,并且指向两个不同enum
类型的指针可能具有不同的实现。由于不允许向前引用enum
类型,所以这不是问题。
答案 1 :(得分:1)
与许多其他问题一样,该问题的答案在于启用了警告的情况下运行编译器。
$ gcc example.c -Wall -pedantic
example.c:3:5: warning: ISO C forbids forward references to ‘enum’ types [-Wpedantic]
TAG x;
^
example.c:5:15: warning: ISO C forbids forward references to ‘enum’ types [-Wpedantic]
void take(TAG x* X) { (void)X; }
^
example.c: In function ‘main’:
example.c:9:7: warning: ISO C forbids forward references to ‘enum’ types [-Wpedantic]
TAG x *xp = 0;
^
example.c: At top level:
example.c:11:2: warning: ISO C does not allow extra ‘;’ outside of a function [-Wpedantic]
};