【问题标题】:Why does `(void *)&` get the address of the variable?为什么`(void *)&`获取变量的地址?
【发布时间】:2021-08-06 11:13:42
【问题描述】:

有人能解释一下这背后的逻辑吗?为什么void?例如

#include <iostream>
using namespace std;
int main()
{
    char c;
    cout << (void *)&c;
    return 0;
}

【问题讨论】:

    标签: c++ casting operator-overloading c-strings void-pointers


    【解决方案1】:
    cout << (void *)&c;
    

    获取c的地址,然后将其转换为void*,然后打印指针。

    这里的目的是打印变量c的地址。但是当将char * 传递给std::cout &lt;&lt; 时,它将尝试打印一个以空字符结尾的字符串。为避免这种情况(并打印实际地址),您必须先转换为 void*


    更多解释:

    std::ostream::operator&lt;&lt; 具有处理char *const char*overload (2)。它假定const char* 将指向最终以空字符'\0' 终止的某个字符串。这只是 C 和 C++ 中使用的约定。

    您想避免这种情况,而是使用overload (7) 来打印地址。

    【讨论】:

    • 那么当且仅当变量为 NULL 时,我是否需要将其转换为 void*
    • @anon 没有。仅当您要打印char 的地址时,即char *const char*
    【解决方案2】:

    为什么(void *)&amp;会得到变量的地址?

    一元&amp; 是地址运算符。 addressof 运算符获取操作数的地址,因为这是该运算符的目的。

    为什么无效?

    因为

    1. &amp;c 的类型是char*,并且该类型的指针被输出流视为指向以空字符结尾的字符串的指针,其处理方式与所有其他指针不同。具体来说,将输出字符串的内容。将不是指向空终止字符串的指针的char* 插入到字符流中会导致未定义的行为。 &amp;c 不是指向以空字符结尾的字符串的指针。将另一种类型的指针插入字符流将导致输出地址的数字表示形式。

      该示例将&amp;c 转换为另一种指针类型,这样它就不会被视为以空字符结尾的字符串。

    2. 所有对象指针都可以转换为void*,因此这是通常选择用于输出字符地址的指针类型。


    更详细一点,字符流插入操作符有重载:

    operator<<(ostrea&, const char*);
    operator<<(ostrea&, const void*); // I'm cheating a bit
                                      // this is technically a member overload
    

    那么当且仅当变量为 NULL 时,我是否需要将其转换为 void*?

    一点也不。变量c 不为空。并且指针是否为空对是否需要转换为void*没有影响。

    还请注意,空终止符 - 终止空终止字符串 - 不是空指针。并且空指针不是指向空终止符的指针。这些是完全不同的概念。

    【讨论】:

      【解决方案3】:

      operator &lt;&lt;char * 类型的对象重载,这样它输出字符就好像使用的指针是指向 C 字符串的第一个字符的指针(以零结尾的字符序列字符'\0')。

      没有强制转换的表达式&amp;c 的类型为char *。因此,运算符假定传递的指针表达式 &amp;c 提供了一个指向 C 字符串的指针。

      要输出对象c 的地址,您需要将表达式&amp;c 转换为void * 类型。

      这是一个演示差异的简单程序。

      #include <iostream>
      
      int main() 
      {
          const char *s = "Hello";
          
          std::cout << s << '\n';
          std::cout << static_cast<const void *>( s ) << '\n';
          
          return 0;
      }
      

      程序输出是

      Hello
      0x5598fd4a3004
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多