c++ - 如何创建不破坏严格别名的 uint8_t 数组?

标签 c++ pointers c++11 strict-aliasing

我最近问了这个问题:

Using this pointer causes strange deoptimization in hot loop

问题是我正在写入类型为 uint8_t 的数组,编译器将其视为可以使用方法的 this 指针(类型struct T*),因为 void*char* (=uint8_t*) 总是可以别名任何其他指针在 C++ 中。此行为导致错失优化机会。当然,我想避免这种情况。所以问题是:我能否声明一个 uint8_t 数组来强制执行严格的别名,即编译器将其视为从不与任何其他类型的指针别名?即,我正在寻找类似 strict_uint8_t 类型的东西,它是具有特殊别名行为的 uint8_t 。有办法实现吗?

显示我的意思的示例代码,借鉴了其他问题并进行了简化。有关详细信息,请阅读链接的问题及其接受的答案:

struct T{
   uint8_t* target;
   void unpack3bit(char* source, int size) {
        while(size > 0){
           uint64_t t = *reinterpret_cast<uint64_t*>(source);
           /** `this->target` cannot be cached in a register here but has
               to be reloaded 16 times because the compiler
               thinks that `this->target` could alias with `this` itself.
               What I want is a special uint8_t type that does not trigger
               this behaviour. */
           this->target[0] = t & 0x7; 
           this->target[1] = (t >> 3) & 0x7;
           this->target[2] = (t >> 6) & 0x7;
           this->target[3] = (t >> 9) & 0x7;
           this->target[4] = (t >> 12) & 0x7;
           this->target[5] = (t >> 15) & 0x7;
           this->target[6] = (t >> 18) & 0x7;
           this->target[7] = (t >> 21) & 0x7;
           this->target[8] = (t >> 24) & 0x7;
           this->target[9] = (t >> 27) & 0x7;
           this->target[10] = (t >> 30) & 0x7;
           this->target[11] = (t >> 33) & 0x7;
           this->target[12] = (t >> 36) & 0x7;
           this->target[13] = (t >> 39) & 0x7;
           this->target[14] = (t >> 42) & 0x7;
           this->target[15] = (t >> 45) & 0x7;
           source+=6;
           size-=6;
           target+=16;
        }
}
};

最佳答案

您可以使用基本类型 uint8_t 的固定大小枚举:

enum strict_uint8_t : uint8_t {};

如果您希望能够透明地与 uint8_t 进行相互转换,您可以将其包装在一个带有转换构造函数和转换运算符的 struct 中:

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

这似乎消除了 gcc 和 clang 中的别名悲观化:https://godbolt.org/g/9Ta98b

(注意:之前的方法,使用位域,在 gcc 中有效,但在 clang 中无效。)

关于c++ - 如何创建不破坏严格别名的 uint8_t 数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26297571/

相关文章:

c++ - 使用静态函数变量与类变量来存储一些状态

c - 指针增量导致段错误

c++ - 使用 range-for 循环 : too few arguments to function call, 未指定单个参数 'a'

linux - 使用 CMAKE 编译静态可执行文件

c++ - QLabel 占用完整空间

java - QAndroidJNI调用方法错误

c++ - clang 格式在单行上捕获空语句

c - 我在 C 中的字符串填充函数不起作用?

c - 指针和二维数组的问题(内存的动态分配)

c++ - std::unique_ptr::release() 与 std::move()