C++ 神秘结构赋值与 int 截断

标签 c++ struct unions

我有以下代码 (c++11) :

#include <iostream>

using namespace std;

//Icons
typedef struct
{
    union
    {
        struct
        {
            uint8_t a  : 1;
            uint8_t b  : 1;
            uint8_t c  : 1;
            uint8_t : 5;
        };
        uint8_t Data;
    } Bla;

    union
    {
        struct
        {
            uint8_t d  : 1;
            uint8_t e  : 1;
            uint8_t : 6;
        };
        uint8_t Data;
    } Foo;

    union
    {
        struct
        {
            uint8_t f   : 1;
            uint8_t g   : 1;
            uint8_t h   : 1;
            uint8_t i   : 1;
            uint8_t : 4;
        };
        uint8_t Data;
    } Bar;
}TypeStruct;

int main()
{

    static constexpr TypeStruct NONE    = {0x00,0,0}; 
    static constexpr TypeStruct A =       {0x01,0,0};    
    static constexpr TypeStruct B   =     {0x02,0,0};     
    static constexpr TypeStruct C     =   {0x04,0,0};    

   return 0;
}

使用 IAR 编译和工作正常,但是使用迂腐的 GCC,我得到以下错误,这困扰了我几天......

$g++ -std=c++11 -o main *.cpp
main.cpp: In function ‘int main()’:
main.cpp:50:52: warning: large integer implicitly truncated to unsigned type [-Woverflow]
     static constexpr TypeStruct B   =     {0x02,0,0};
                                                    ^
main.cpp:51:52: warning: large integer implicitly truncated to unsigned type [-Woverflow]
     static constexpr TypeStruct C     =   {0x04,0,0};
                                                    ^

我不明白为什么! 也许与 union 有关,但我尝试了不同的着作,但没有匹配: {1,0,0} 或 {{1},{0},{0}} 或 {{1,0,0}} 问题是我需要在特化中使用类似“A”的东西,这不能改变,比方说:

MyClass:MyMotherClass(TypeStruct A);

谢谢


编辑: 选择的解决方案是使用:

static constexpr TypeStruct A   =   {{1,0,0},{0,0},{0,0,0,0}};     
static constexpr TypeStruct B   =   {{0,1,0},{0,0},{0,0,0,0}};      
static constexpr TypeStruct C   =   {{0,0,1},{0,0},{0,0,0,0}};  
etc...

但是,通过使用 IAR 和 GCC 编译的这个解决方案,我得到了以下 PC lint 消息,优先级:高,类别:4397。

 "pc lint constexpr variable 'A' must be initialized by a constant expression"
 "pc lint constexpr variable 'B' must be initialized by a constant expression"
 "pc lint constexpr variable 'C' must be initialized by a constant expression"

最佳答案

初始化应用于位域结构,因为它在 union 中首先声明。 (将 uint8_t 数据成员放在第一位,然后看到警告消失)。结果 0x02 和 0x04 对于第一个成员 (uint8_t a) 来说太大了。

您可以通过显式指定位域初始化来解决此问题,例如

static constexpr TypeStruct B   =   {{0,1},0,0};     
static constexpr TypeStruct C   =   {{0,0,1},0,0};    

请注意,一般而言,不能保证位域将对应于字节(或其他整数类型)中的位位置 - 这取决于编译器。因此,使用字节值(如 0x02 和 0x04)直接初始化位域结构一开始并不是一个好主意。

关于C++ 神秘结构赋值与 int 截断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54006806/

相关文章:

Const Struct 与 Const 成员的结构

c - 指向函数的指针如何在 C 中发挥作用?

c - 使用 C 中的结构 union

c++ - 使用 union 体通过 SPI 将 float 从一个 arduino 发送到另一个 arduino

c - 我应该使用 union 来加速执行时间吗?

c++ - Windows CE - 禁用 CComboBox 突出显示

c++ - 在qt中从https读取Json

c++ - C++ 中的 vector 容器和静态绑定(bind)?

c++ - 围绕某个点旋转对象,即使原始枢轴不同?

c - 更新结构的内容