Предупреждение: бросок увеличивает требуемое выравнивание

Я недавно работаю над этой платформой, для которой выходит кодовая база прежней версии, большое количество "увеличений броска потребовало выравнивания к N" предупреждения, где N является размером цели броска.

struct Message
{
   int32_t id;
   int32_t type;
   int8_t  data[16];
};

int32_t GetMessageInt(const Message& m)
{
   return *reinterpret_cast<int32_t*>(&data[0]);
}

Надо надеяться, очевидно, что "реальная" реализация была бы немного более сложной, но основной пункт - то, что у меня есть данные, прибывающие из где-нибудь, я знаю, что это выровнялось (потому что мне нужны идентификатор и тип, чтобы быть выровненный), и все же я получаю сообщение, что бросок увеличивает выравнивание, в случае в качестве примера, к 4.

Теперь я знаю, что могу подавить предупреждение с аргументом компилятору, и я знаю, что могу бросить бит в круглых скобках для освобождения* сначала, но я действительно не хочу проходить каждый бит кода, для которого нужен этот вид управления (существует много, потому что мы загружаем много данных прочь диска, и те данные входят, поскольку символ буферизует так, чтобы мы могли легко усовершенствование указателя), но кто-либо может дать мне какие-либо другие мысли об этой проблеме? Я имею в виду, мне на такую важную и общую опцию кажется, что Вы не хотели бы предупреждать, и если существует на самом деле возможность выполнения его неправильно затем, подавление предупреждения не собирается помогать. Наконец, разве компилятор не может знать, как я делаю, как рассматриваемый объект на самом деле выровненный в структуре, таким образом, это должно смочь не волноваться о выравнивании на том конкретном объекте, если это не было ударено байт или два?

8
задан dash-tom-bang 30 April 2010 в 01:24
поделиться

1 ответ

Одной из возможных альтернатив может быть:

int32_t GetMessageInt(const Message& m)
{
   int32_t value;
   memcpy(&value, &(data[0]), sizeof(int32_t));
   return value;
}

Для архитектуры x86 выравнивание не имеет большого значения, это скорее проблема производительности, которая на самом деле не актуальна для код, который вы предоставили. Для других архитектур (например, MIPS) неправильный доступ вызывает исключения ЦП.


Хорошо, вот еще одна альтернатива:

struct Message
{
    int32_t id;
    int32_t type;
    union
    {
        int8_t  data[16];
        int32_t data_as_int32[16 * sizeof(int8_t) / sizeof(int32_t)];
        // Others as required
    };
};

int32_t GetMessageInt(const Message& m)
{
    return m.data_as_int32[0];
}

Вот вариант выше, который включает предложения из cpstubing06 :

template <size_t N>
struct Message
{
    int32_t id;
    int32_t type;
    union
    {
        int8_t  data[N];
        int32_t data_as_int32[N * sizeof(int8_t) / sizeof(int32_t)];
        // Others as required
    };
    static_assert((N * sizeof(int8_t) % sizeof(int32_t)) == 0,
                  "N is not a multiple of sizeof(int32_t)");
};

int32_t GetMessageInt(const Message<16>& m)
{
    return m.data_as_int32[0];
}


// Runtime size checks
template <size_t N>
void CheckSize()
{
    assert(sizeof(Message<N>) == N * sizeof(int8_t) + 2 * sizeof(int32_t));
}

void CheckSizes()
{
    CheckSize<8>();
    CheckSize<16>();
    // Others as required
}
3
ответ дан 6 December 2019 в 00:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: