为什么`(void *)&`获取变量的地址?

Why does `(void *)&` get the address of the variable?

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

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

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

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


更多解释:

std::ostream::operator<< 具有处理 char *const char*overload (2)。它假定 const char* 将指向某个最终由空字符 '[=21=]' 终止的字符串。这只是 C 和 C++ 中使用的约定。

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

Why does (void *)& get the address of the variable?

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

Why void?

因为

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

    该示例将 &c 转换为另一种指针类型,这样它就不会被视为空终止字符串。

  2. 所有的对象指针都可以转换成void*,所以也就是通常选择的输出字符地址的指针类型


关于更多细节,字符流插入运算符有重载:

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

So would I need to convert it to void* when and only when a variable is NULL?

完全没有。变量 c 不为空。而一个指针是否为null对是否需要转换为void*.

没有影响

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

operator << 为类型 char * 的对象重载,这样它输出字符就好像使用的指针是指向 C 字符串(序列)的第一个字符的指针以零字符终止的字符数 '[=14=]').

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

要输出对象 c 的地址,您需要将表达式 &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