C++ 在GCC中,相同类型和相同变量的联合会抛出错误,但在Visual C++;
我在头文件中声明了以下代码:C++ 在GCC中,相同类型和相同变量的联合会抛出错误,但在Visual C++;,c++,visual-studio,gcc,visual-c++,unions,C++,Visual Studio,Gcc,Visual C++,Unions,我在头文件中声明了以下代码: //Integer Vector4D stuffs typedef union { size_t data[4]; struct { size_t x; size_t y; size_t z; size_t w; }; struct { size_t x; size_t y; size_t width; s
//Integer Vector4D stuffs
typedef union {
size_t data[4];
struct {
size_t x;
size_t y;
size_t z;
size_t w;
};
struct {
size_t x;
size_t y;
size_t width;
size_t height;
};
} Vector4Di;
//End Integer Vector4D stuffs
我正在为Windows和Linux编译代码。我正在将Windows10Pro与WSL一起使用
这是我从Microsoft Visual Studio 2017获得的编译生成输出:
1>------ Build started: Project: SDL, Configuration: Debug x64 ------
1>C:main_pc.cpp
1>1 File(s) copied
1>block.cpp
1>common.cpp
1>draw.cpp
1>game.cpp
1>input.cpp
1>main.cpp
1>Generating Code...
1>SDL.vcxproj -> C:\Users\tom_mai78101\Documents\VSProjects\SDL\x64\Debug\SDL.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
根据上面的生成日志,这表明编译时生成已成功
但是,相同的源代码会在GCC中抛出错误:
$ make
clean ...
build ...
main.cpp
In file included from /mnt/c/Users/tom_mai78101/Documents/VSProjects/SDL/SDL/../SDL/main.cpp:1:0:
/mnt/c/Users/tom_mai78101/Documents/VSProjects/SDL/SDL/../SDL/game/common.h: At global scope:
/mnt/c/Users/tom_mai78101/Documents/VSProjects/SDL/SDL/../SDL/game/common.h:358:10: error: redeclaration of 'size_t <unnamed union>::<unnamed struct>::x'
size_t x;
^
/mnt/c/Users/tom_mai78101/Documents/VSProjects/SDL/SDL/../SDL/game/common.h:352:10: note: previous declaration 'size_t <unnamed union>::<unnamed struct>::x'
size_t x;
^
/mnt/c/Users/tom_mai78101/Documents/VSProjects/SDL/SDL/../SDL/game/common.h:359:10: error: redeclaration of 'size_t <unnamed union>::<unnamed struct>::y'
size_t y;
^
/mnt/c/Users/tom_mai78101/Documents/VSProjects/SDL/SDL/../SDL/game/common.h:353:10: note: previous declaration 'size_t <unnamed union>::<unnamed struct>::y'
size_t y;
^
$make
清洁的
建造。。。
main.cpp
文件包括在/mnt/c/Users/tom_mai78101/Documents/VSProjects/SDL/SDL/。/SDL/main.cpp:1:0:
/mnt/c/Users/tom_mai78101/Documents/VSProjects/SDL/SDL/。/SDL/game/common.h:在全球范围内:
/mnt/c/Users/tom_mai78101/Documents/VSProjects/SDL/SDL/。/SDL/game/common.h:358:10:错误:重新声明“大小”:
尺寸x;
^
/mnt/c/Users/tom_mai78101/Documents/VSProjects/SDL/SDL/。/SDL/game/common.h:352:10:注意:以前的声明'size\u t::::x'
尺寸x;
^
/mnt/c/Users/tom_mai78101/Documents/VSProjects/SDL/SDL/。/SDL/game/common.h:359:10:错误:重新声明“大小”:
大小;
^
/mnt/c/Users/tom_mai78101/Documents/VSProjects/SDL/SDL/。/SDL/game/common.h:353:10:注意:以前的声明'size\u t:::'y'
大小;
^
要点是,在GCC中,它会抱怨大小如何代码>和<代码>大小代码>都在联合内部重新声明,Vector4Di
。但是MSBuild没有抛出与此相关的错误,它成功地编译了代码。
据我所知,我认为具有相同类型和相同变量名的联合不应该与另一个联合冲突,特别是当变量位于结构中时。特别是在为C++11编译时,众所周知C++11对联合有更好的支持
我可以问一下为什么它会抛出GCC错误吗?我应该如何修复此错误以使MSBuild和GCC都成功编译
提前谢谢。好的,这是我今天学到的东西。也就是说C++没有很好的处理匿名结构/联盟。根据注释,我应该向结构和联合添加标记名 这就是新的修改版本:
//Integer Vector4D stuffs
typedef union {
size_t data[4];
struct quaternion {
size_t x;
size_t y;
size_t z;
size_t w;
} quaternion;
struct rect {
size_t x;
size_t y;
size_t width;
size_t height;
} rect;
} Vector4Di;
//End Integer Vector4D stuffs
现在,VisualStudio和GCC都可以很好地编译相同的项目和源代码,并且不再在重新声明相同名称和类型的变量时抛出错误。我也不需要修改其余的代码来适应新的更改,尽管这个Vector4Di
struct是在标题中声明的,所以这是一个很好的修复
感谢MyooTIALI的帮助。
< P> C++标准不承认匿名<代码> Stutt不用于在<代码>联合< /COD>中定义其类型的成员;使用匿名<代码> Stutt将其成员加入到封闭的结构中声明两个同名的成员一样;实际上他说:
决不能创建导致字段定义不明确的结构。例如,在此结构中:
struct {
int a;
struct {
int a;
};
} foo;
用foo.a
引用哪个a是不明确的。编译器为此类构造提供错误
所以,这不是你可以用编译器开关或其他东西解决的问题;gcc不支持它,句号
这一愿景得到了唯一一个正式描述这一特征的标准的确认,即ISO C 11标准;在§6.7.2.1¨13中指出:
没有标记的结构类型的未命名成员称为匿名结构;没有标记的联合类型的未命名成员称为匿名联合。匿名结构或联合的成员被视为包含结构或联合的成员。如果包含的结构或联合也是匿名的,则递归地应用
结构的命名成员必须具有唯一的名称
因此,总结一下:
<> >如果你想把它变成标准的C++,你必须给你的子结构命名。你可以做:
union Vector4Di {
size_t data[4];
struct {
size_t x;
size_t y;
size_t z;
size_t w;
} q;
struct {
size_t x;
size_t y;
size_t width;
size_t height;
} r;
};
调整代码的其余部分,并对其感到满意
如果您同意使用这些扩展,您仍然可以通过在第二个struct
中以不同的方式命名x
和y
使其工作,如:
union Vector4Di {
size_t data[4];
struct {
size_t x;
size_t y;
size_t z;
size_t w;
};
struct {
size_t dummy_x;
size_t dummy_y;
size_t width;
size_t height;
};
};
在这种情况下,您可以自由地使用x
和y
和宽度
和高度
,而且我怀疑这在标准方面几乎没有问题-如果我们忽略“匿名结构”的话;这两个结构是标准布局,并且布局兼容,因此标准保证您可以使用您喜欢的任何名称检查“公共初始序列”
该标准不允许在联合中使用未命名结构,因此您已经处于未授权区域;每个编译器决定对它做什么都是他自己喜欢的扩展,所以你得到你得到的。如果您希望安全,请为每个结构声明一个命名成员。@Deduplicator:在这种情况下,他将获得共享相同内存的.x
和.width
,这肯定不是他想要的。@MatteoItalia哦,真的吗?“我可以解决这个问题。@重复数据消除程序:两者都可以,并拒绝它。嗯,它们都可以接受。”