Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在GCC中,相同类型和相同变量的联合会抛出错误,但在Visual C++;_C++_Visual Studio_Gcc_Visual C++_Unions - Fatal编程技术网

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将其成员加入到封闭的中,但是它不是标准C++,所以它没有严格定义该机制是如何工作的。 特别是,在这里,您正在危险的水域中行走,因为您有两个匿名结构,其成员具有相同的名称;从C++标准的观点来看,这绝对是模糊的,因为当你做“代码> V4D.x=5;<代码>

没有描述在这种情况下会发生什么;一个快速的检查告诉我-它似乎只是指第一个被定义的匿名结构的成员,如果你问我,这是完全疯狂的

相反,gcc确实会发疯,因为这就像在同一个
结构中声明两个同名的成员一样;实际上他说:

决不能创建导致字段定义不明确的结构。例如,在此结构中:

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哦,真的吗?“我可以解决这个问题。@重复数据消除程序:两者都可以,并拒绝它。嗯,它们都可以接受。”