Как обойти strict aliasing rule?
От: Eeel Россия  
Дата: 16.06.16 22:40
Оценка: 3 (1)
У меня есть некая структурка данных, и к ней надо обращаться то как к двум 32-битным беззнаковым интам, то как к одному 64-битному беззнаковому инту.

По сути, это union. Но, насколько я понимаю, через union по стандарту C++ этого делать нельзя, так как это нарушение strict aliasing и UB (записывать один тип, а читать другой, несовместимый, тип).

struct Foo
{
    union
    {
        std::uint64_t value64;

        struct 
        {
            std::uint32_t value32Lo;

            std::uint32_t value32Hi;           
        };
    };
};


Есть очевидное решение через битовые операции, но я бы не хотел просто надеяться на компилятор — на то, что он избавится от битовых операций самостоятельно (и не будет делать сдвиги и маски, а будет загружать либо 64-битное слово в 64-битный регистр, либо два 32-битных слова в 32-битные регистры, или применит векторизацию), а хотел бы какое-то гарантированно эффективное решение, соответствующее при этом стандарту.

Еще у меня была мысль про буфер char'ов: по стандарту любой тип можно алиазить массивом чаров, тогда что если записать этот в массив std::uint64_t, а прочитать два std::uint32_t — будет ли это нарушением strict aliasing rule? Очевидный ответ — да, поскольку читается один тип, а записывается другой. А может и нет. Этот момент мне неясен.

struct Foo
{
    alignas(std::uint64_t) char buffer[sizeof(std::uint64_t)];
};
Отредактировано 27.06.2016 9:56 S. Schlongberg . Предыдущая версия . Еще …
Отредактировано 21.06.2016 16:20 S. Schlongberg . Предыдущая версия .
Отредактировано 21.06.2016 9:55 S. Schlongberg . Предыдущая версия .
Отредактировано 21.06.2016 9:55 S. Schlongberg . Предыдущая версия .
Отредактировано 17.06.2016 21:01 S. Schlongberg . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.