C ++ Mystic структура присваивания с усеченным int - PullRequest
0 голосов
/ 02 января 2019

У меня есть следующий код (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}} Проблема в том, что мне нужно использовать что-то вроде «А» в специализации, и это нельзя изменить, скажем:

MyClass:MyMotherClass(TypeStruct A);

Спасибо


EDIT: Выбранное решение использовало:

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, я получаю следующее сообщение ПК, приоритет: высокий, категория: 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 голосов
/ 09 апреля 2019

Решение для получения кода, компилируемого с 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...
0 голосов
/ 02 января 2019

Инициализации применяются к структуре битового поля, потому что она объявляется первой в объединении. (Сначала поместите элемент данных 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, была плохой идеей для начала.

...