截断了整数的C ++神秘结构分配

时间:2019-01-02 12:56:59

标签: 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};
                                                    ^

我不明白为什么! 也许与工会有关,但我尝试了不同的著作,但没有匹配:  {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皮棉消息,“优先级:高,类别: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"

2 个答案:

答案 0 :(得分:3)

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

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

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

请注意,通常不能保证位域将与字节(或其他整数类型)中的位位置相对应-由编译器决定。因此,直接用字节值(例如0x02和0x04)初始化位域结构是一个糟糕的主意。

答案 1 :(得分:0)

一种用于使用IAR和GCC编译代码并避免PC-lint错误#4397的解决方案:

static const应该代替static constexpr

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