mingw 的 gcc-5.3 下具有混合位域和枚举 decls 的意外 sizeof 结构

Posted

技术标签:

【中文标题】mingw 的 gcc-5.3 下具有混合位域和枚举 decls 的意外 sizeof 结构【英文标题】:Unexpected sizeof struct with mixed bitfields and enum decls under mingw's gcc-5.3 【发布时间】:2017-03-16 11:32:40 【问题描述】:

我遇到了 mingw gcc 的奇怪问题,sizeof(X) 在以下示例中返回 8 而不是 4:

struct X

      enum E e1, e2, e3;
      uint32_t v:2;
      enum E2 ee1, ee2, ee3;
      uint32_t vv:1;
;

如果我把它改成

struct X

      enum E e1, e2, e3;
      enum E2 ee1, ee2, ee3;
      uint32_t v:2;
      uint32_t vv:1;
;

结果如预期的那样变为 4。 我知道位域的对齐、排序和其他东西是实现定义的,但是 Linux 下的相同 gcc 5.3 给出了 4 个样本。 正如我的观点,枚举声明不能扩大结构的大小并影响位字段包装。那么第一个声明有什么问题呢? 这是编译命令行:

C:/Qt/Qt5.7.1/Tools/mingw530_32/bin/mingw32-make -f Makefile.Release
mingw32-make[1]: Entering directory 'C:/Users/Documents/build-tst-Desktop_Qt_5_7_1_MinGW_32bit-Release'
g++ -c -pipe -fno-keep-inline-dllexport -std=c++1z -std=gnu++1z -O2 -std=gnu++1z -frtti -Wall -Wextra -fexceptions -mthreads -DUNICODE -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_SQL_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I..\tst -I. -I..\tst\magic_get\include -Ic://boost_1_62_0 -I..\..\..\..\Qt\Qt5.7.1\5.7\mingw53_32\include -I..\..\..\..\Qt\Qt5.7.1\5.7\mingw53_32\include\QtWidgets -I..\..\..\..\Qt\Qt5.7.1\5.7\mingw53_32\include\QtGui -I..\..\..\..\Qt\Qt5.7.1\5.7\mingw53_32\include\QtANGLE -I..\..\..\..\Qt\Qt5.7.1\5.7\mingw53_32\include\QtNetwork -I..\..\..\..\Qt\Qt5.7.1\5.7\mingw53_32\include\QtSql -I..\..\..\..\Qt\Qt5.7.1\5.7\mingw53_32\include\QtCore -Irelease -I. -I..\..\..\..\Qt\Qt5.7.1\5.7\mingw53_32\mkspecs\win32-g++  -o release\main.o ..\tst\main.cpp
g++ -Wl,-s -Wl,-subsystem,windows -mthreads -o release\tst.exe release/main.o release/mainwindow.o release/moc_mainwindow.o  -lmingw32 -LC:\Qt\Qt5.7.1\5.7\mingw53_32\lib C:\Qt\Qt5.7.1\5.7\mingw53_32\lib\libqtmain.a -lshell32 -LC:\utils\my_sql\my_sql\lib -LC:\utils\postgresql\pgsql\lib C:\Qt\Qt5.7.1\5.7\mingw53_32\lib\libQt5Widgets.a C:\Qt\Qt5.7.1\5.7\mingw53_32\lib\libQt5Gui.a C:\Qt\Qt5.7.1\5.7\mingw53_32\lib\libQt5Network.a C:\Qt\Qt5.7.1\5.7\mingw53_32\lib\libQt5Sql.a C:\Qt\Qt5.7.1\5.7\mingw53_32\lib\libQt5Core.a 
mingw32-make[1]: Leaving directory 'C:/Users/Documents/build-tst-Desktop_Qt_5_7_1_MinGW_32bit-Release'  

可以在http://coliru.stacked-crooked.com/a/62d3a09d10fcc648 找到按预期工作的完整示例 不幸的是我没有找到在线mingw显示出意外的结果。

【问题讨论】:

而且链接不指向有效的例子:) @Anty 它不是全尺寸整数,它是一个位字段,请在问题下方查看示例 @Lundin 我应该是 4,但得到了 8 在 Windows 上我得到 8,在 Linux 上我得到 4。为什么我应该期望 12 或 16? v 和 vv 是位域,应该打包成一个 uint32_t @Lundin 这是一个 C++ 代码,不是 C,它是有效的,我使用枚举的具体值出结构。 【参考方案1】:

看起来与 MSVC 兼容是 gcc 的一个“特性”。

https://gcc.gnu.org/onlinedocs/gcc/x86-Variable-Attributes.html

请尝试

1) 添加属性

struct __attribute__((gcc_struct)) X

      enum E e1, e2, e3;
      uint32_t v:2;
      enum E2 ee1, ee2, ee3;
      uint32_t vv:1;
;

2) 添加编译选项-mno-ms-bitfields

【讨论】:

太好了,谢谢。它可以分别与 __attribute__ 和 -mno-ms-bitfields 一起使用,所以我可以自己使用一个或另一个

以上是关于mingw 的 gcc-5.3 下具有混合位域和枚举 decls 的意外 sizeof 结构的主要内容,如果未能解决你的问题,请参考以下文章

编译器玄学研究报告第一期——位域和volatile

C++ Primer 5th笔记(chap 19 特殊工具与技术)两种不可移植的特性之“位域”

具有非连续布局的 C 位域元素

C 和 C++ 中的位域:它们在哪里使用?

如何在 CentOS 7.2 上使用 yum 安装 gcc 5.3?

混合开发环境