How to create an uint8_t array that does not undermine strict aliasing?

家住魔仙堡 提交于 2019-12-05 04:58:31

You can use a fixed-size enumeration with base type uint8_t:

enum strict_uint8_t : uint8_t {};

If you want to be able to convert to and from uint8_t transparently, you can wrap it in a struct with converting constructor and conversion operator:

struct strict_uint8_t {
    enum : uint8_t {} i;
    strict_uint8_t(uint8_t i) : i{i} {}
    operator uint8_t() const { return i; }
};

This appears to eliminate the aliasing pessimization in gcc and clang: https://godbolt.org/g/9Ta98b

(Note: the previous approach, using a bitfield, worked in gcc but not in clang.)

In visual studio you can use __declspec(restict) for functions and __restrict for variables to tell the compiler that the pointer is alias free. I believe that in other compilers like GCC there is a __restrict__ attribute (but I'm not sure). For more info see here

I believe you'll get rid of the aliasing if you pass both pointers through a function where the pointers are declared with restrict. That's non-standard compiler extension though, e.g. in the case of g++:

#include <cstdint>
#include <climits>

struct T{
   uint8_t* target;
  private:
    void unpack3bit(char*__restrict__ source, int size, uint8_t*__restrict__ dst) {
        while(size > 0){
           uint64_t t = *source;
           dst[0] = t & 0x7; 
           dst[1] = (t >> 3) & 0x7;
           dst[2] = (t >> 6) & 0x7;
           dst[3] = (t >> 9) & 0x7;
           dst[4] = (t >> 12) & 0x7;
           dst[5] = (t >> 15) & 0x7;
           dst[6] = (t >> 18) & 0x7;
           dst[7] = (t >> 21) & 0x7;
           dst[8] = (t >> 24) & 0x7;
           dst[9] = (t >> 27) & 0x7;
           dst[10] = (t >> 30) & 0x7;
           dst[11] = (t >> 33) & 0x7;
           dst[12] = (t >> 36) & 0x7;
           dst[13] = (t >> 39) & 0x7;
           dst[14] = (t >> 42) & 0x7;
           dst[15] = (t >> 45) & 0x7;
           source+=6;
           size-=6;
           target+=16;
        }
    }
public:
   void unpack3bit(char* source, int size) {
       unpack3bit(source,size,this->target);
   }

};

void f(int i, T& t, char* source) {
  t.unpack3bit(source, i); 
}

Online: http://goo.gl/SCjpL6

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!