V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dangyuluo
V2EX  ›  C++

LLVM 的`addressof`实现为什么这么奇怪

  •  
  •   dangyuluo · 2022-01-10 13:46:50 +08:00 · 1646 次点击
    这是一个创建于 1042 天前的主题,其中的信息可能已经有所发展或是发生改变。
    template <class _Tp>
    inline _LIBCPP_NO_CFI _LIBCPP_INLINE_VISIBILITY
    _Tp*
    addressof(_Tp& __x) _NOEXCEPT
    {
      return reinterpret_cast<_Tp *>(
          const_cast<char *>(&reinterpret_cast<const volatile char &>(__x)));
    }
    

    一个&可以实现的功能,reinterpret_cast几次的意义是什么?谢谢

    3 条回复    2022-01-11 12:09:42 +08:00
    joydee
        1
    joydee  
       2022-01-10 14:03:12 +08:00
    1. 其实 GCC 也有这个函数:
    参考: GCC4.7.1
    `template<typename _Tp>
    inline _Tp*
    __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
    {
    return reinterpret_cast<_Tp*>
    (&const_cast<char&>(reinterpret_cast<const volatile char&>(__r)));
    }`

    2. stackoverflow 上面有对这个实现的具体解释<https://stackoverflow.com/questions/16195032/implementation-of-addressof>

    简短概括就是:
    1) typename __Tp& 可能是 const | volatile ,所以需要 reinterpret_cast ,但是 reinterpret_cast 不能做 remove type 操作,所以需要 const_cast,至于为何选用 char 型,因为可能 char 型指针没有 alignment 显式要求。
    dangyuluo
        2
    dangyuluo  
    OP
       2022-01-10 14:04:59 +08:00
    @joydee 哦懂了,就是说甭管有没有 CV ,先用`reinterpret_cast`添加上再说,然后再去掉。选用 char 其实是可以理解的因为是对齐最小的 type 了
    qbqbqbqb
        3
    qbqbqbqb  
       2022-01-11 12:09:42 +08:00
    单用&肯定不行,因为&运算符是可以重载的。

    选用 char 一是因为内置类型不可重载运算符,保证&一定是取地址的功能;二是不违反 strict aliasing rule (除 char 类型以外不允许其它的不同类型的指针指向同一段内存,否则是未定义行为)。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5795 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 01:45 · PVG 09:45 · LAX 17:45 · JFK 20:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.