c – 如何创建一个不破坏严格别名的uint8_t数组?

前端之家收集整理的这篇文章主要介绍了c – 如何创建一个不破坏严格别名的uint8_t数组?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我最近问了这个问题:

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.有没有办法实现这个目标?

显示我的意思的示例代码,借用其他问题并简化.有关更多详细信息,请阅读链接的问题及其接受的答案:

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

解决方法

您可以使用基本类型为uint8_t的固定大小的枚举:
  1. enum strict_uint8_t : uint8_t {};

如果您希望能够透明地转换为uint8_t和从uint8_t转换,可以将其包含在转换构造函数和转换运算符的结构中:

  1. struct strict_uint8_t {
  2. enum : uint8_t {} i;
  3. strict_uint8_t(uint8_t i) : i{i} {}
  4. operator uint8_t() const { return i; }
  5. };

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

(注意:以前的方法,使用位域,在gcc中工作但不在clang中工作.)

猜你在找的C&C++相关文章