这是this question的后续行动。
我试图避免使用显式的 typedef 通过这样的强制转换将一个数组复制到另一个数组:
#include <stdio.h>
int main(void)
{
int i;
int dst[] = { 10, 20, 30 }, src[] = { 1, 2, 3 };
*(struct{int _[3];}*)dst = *(struct{int _[3];}*)src;
for (i = 0; i < 3; i++) printf("%d\n", dst[i]);
return 0;
}
使用gcc,我得到arrcpy.c:8: error: incompatible types in assignment
,但是使用Open Watcom,它编译得很好(并按照我的预期工作,打印1到3)。
gcc的行为是否符合标准?如果是,那么相关的章节是什么?我无法理解为什么两个相同的类型定义struct{int _[3];}
在gcc眼中不一样(或兼容)。
编辑:我完全知道这是一种糟糕的编码风格。问题是关于另一件事。我很好奇gcc的行为背后是否有合理的理由,如果它是合法的。
答案 0 :(得分:6)
gcc行为是正确的,类型是两个不相关的未命名结构。每个结构虽然具有相同的内存布局,但具有不同的名称。如果你真的想这样做,那就使用typedef。
答案 1 :(得分:1)
为什么不使用memcpy
?
#include <stdio.h>
#include <string.h>
int main(void)
{
int i;
int dst[] = { 10, 20, 30 }, src[] = { 1, 2, 3 };
memcpy(dst, src, 3 * sizeof(int));
for (i = 0; i < 3; i++) printf("%d\n", dst[i]);
return 0;
}
或尺寸,而不是3:sizeof(dst)/sizeof(dst[0])
编辑:通过编辑,我只能假设,与outis' answer一样,编译器将两个结构定义看作是两种不同类型的结构。尽管它们可能包含相同的数据,但它们有两种不同的类型。
答案 2 :(得分:1)
基本上,C中的类型等价不是structural等价.C使用nominative type system。
根据C99的第6.7.2.1-7段:
struct-or-union-specifier中struct-declaration-list的存在在转换单元中声明了一个新类型。 struct-declaration-list是结构或联合成员的一系列声明。如果struct-declaration-list不包含命名成员,则行为未定义。在终止列表的}之前,类型是不完整的。
struct-declaration-list
和struct-or-union-specifier
来自C语法(第6.7.2.1节):
struct-or-union-specifier: struct-or-union identifieropt { struct-declaration-list } struct-or-union: struct union
即使两个不同的结构具有相同的内存布局,它们也是不同的类型。
如果您想避免污染全局命名空间,可以在本地将结构声明为您使用它的函数。
#include <stdio.h>
int main(void) {
// struct T is only visible in main()
struct T {int _[3];};
int i;
int dst[] = { 10, 20, 30 }, src[] = { 1, 2, 3 };
*(struct T*)dst = *(struct T*)src;
for (i = 0; i < 3; i++) printf("%d\n", dst[i]);
return 0;
}
void fails(void) {
// will cause a compilation error, because struct T is an incomplete type.
struct T t;
}
答案 3 :(得分:1)
两个struct
定义不兼容:
来自C99 6.2.7:
如果类型相同,则两种类型具有兼容类型。额外 描述了用于确定两种类型是否兼容的规则 6.7.2中的类型说明符,6.7.3中的类型限定符,以及 6.7.5为声明者。此外,在单独的翻译单元中声明的两个结构,联合或枚举类型是兼容的 如果他们的标签和成员满足以下要求......
类型不一样。如果它们是在单独的翻译单元中声明的,那么它们将是兼容的。
但是,即使它们兼容,您的代码仍会调用未定义的行为,至少有两个原因: