gex*_*ide 8 c++ pointers strict-aliasing c++11
我最近问了这个问题:
问题是我正在写一个类型的数组,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;
}
}
};
Run Code Online (Sandbox Code Playgroud)
您可以使用具有基本类型的固定大小的枚举uint8_t:
enum strict_uint8_t : uint8_t {};
Run Code Online (Sandbox Code Playgroud)
如果您希望能够以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; }
};
Run Code Online (Sandbox Code Playgroud)
这似乎消除了gcc和clang中的别名悲观化:https://godbolt.org/g/9Ta98b
(注意:以前的方法,使用位域,在gcc中工作但不在clang中工作.)