【发布时间】: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
有人能解释一下这背后的逻辑吗?为什么void?例如
#include <iostream>
using namespace std;
int main()
{
char c;
cout << (void *)&c;
return 0;
}
【问题讨论】:
标签: c++ casting operator-overloading c-strings void-pointers
cout << (void *)&c;
获取c的地址,然后将其转换为void*,然后打印指针。
这里的目的是打印变量c的地址。但是当将char * 传递给std::cout << 时,它将尝试打印一个以空字符结尾的字符串。为避免这种情况(并打印实际地址),您必须先转换为 void*。
更多解释:
std::ostream::operator<< 具有处理char * 和const char* 的overload (2)。它假定const char* 将指向最终以空字符'\0' 终止的某个字符串。这只是 C 和 C++ 中使用的约定。
您想避免这种情况,而是使用overload (7) 来打印地址。
【讨论】:
void*?
char 的地址时,即char * 或const char*。
为什么
(void *)&会得到变量的地址?
一元& 是地址运算符。 addressof 运算符获取操作数的地址,因为这是该运算符的目的。
为什么无效?
因为
&c 的类型是char*,并且该类型的指针被输出流视为指向以空字符结尾的字符串的指针,其处理方式与所有其他指针不同。具体来说,将输出字符串的内容。将不是指向空终止字符串的指针的char* 插入到字符流中会导致未定义的行为。 &c 不是指向以空字符结尾的字符串的指针。将另一种类型的指针插入字符流将导致输出地址的数字表示形式。
该示例将&c 转换为另一种指针类型,这样它就不会被视为以空字符结尾的字符串。
所有对象指针都可以转换为void*,因此这是通常选择用于输出字符地址的指针类型。
更详细一点,字符流插入操作符有重载:
operator<<(ostrea&, const char*);
operator<<(ostrea&, const void*); // I'm cheating a bit
// this is technically a member overload
那么当且仅当变量为 NULL 时,我是否需要将其转换为 void*?
一点也不。变量c 不为空。并且指针是否为空对是否需要转换为void*没有影响。
还请注意,空终止符 - 终止空终止字符串 - 不是空指针。并且空指针不是指向空终止符的指针。这些是完全不同的概念。
【讨论】:
operator << 为 char * 类型的对象重载,这样它输出字符就好像使用的指针是指向 C 字符串的第一个字符的指针(以零结尾的字符序列字符'\0')。
没有强制转换的表达式&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
【讨论】: