为什么我在取消引用和不取消引用指针的情况下获得相同的值

Why do I get the same value with and without dereferencing a pointer

本文关键字:取消 引用 情况下 指针 为什么      更新时间:2023-10-16

以下代码:

int number = 65;
char *ptr = reinterpret_cast< char* >(&number);
cout << *ptr << endl;

*ptr打印Aptr打印A。为什么它们都打印相同的结果?

流正在重载<<,因此无论如何都会为char隐式完成取消引用。

更具体地说:由于char *是 C 的stringostream尝试这样读取它,即它取消引用指针并读取 char s,直到找到一个零字节。(这仅适用于正确的字节序。

请考虑以下代码:

#include <iostream>
int main(void) {
        char c = 'A';
        int  i = 66;
        std::cout <<  c << 'n';
        std::cout << &c << 'n';
        std::cout <<  i << 'n';
        std::cout << &i << 'n';
        return 0;
}

在我的机器上(不是全部!(它打印

A
AB
66
0x7fff0d1db1bc

因为c打印正确,但&c被解释为字符串。但是c不是以 null 结尾的,所以ostream继续读取,找到 i 的第一个字节,然后找到一个空字节,因为 i 的值太小了,我们只使用它的四个字节中的一个。

但是,i&i按预期打印。此行为仅适用于char,因为它对其他类型的行为没有意义。

两者都打印相同的结果,因为:

  1. 除其他外,ostream::operator<<char*char都有过载(见这里和这里(。
  2. char*重载将参数解释为指向以 null 结尾的字节字符串的指针,而不是指向单个char的指针。
  3. 显然你的机器是小端序并且有sizeof(char) < sizeof(int)(与==相反(。这意味着 number 占用的内存,当解释为 char s 的数组时,是一个值为 65 的char,后跟一个或多个空 char s。因此,当number被解释为以 null 结尾的字节字符串时,它包含值为 65 的单个字符。

因此,当您流式传输类型为 char*ptr 时,char 重载会打印值为 65 的字符指向。当您流式传输类型 char*ptr 时,char* 重载将打印指向的以 null 结尾的字节字符串,其中包含值为 65 的单个字符,因此再次打印单个字符。

关于第3点的进一步说明:

请注意,给定sizeof(char) < sizeof(int),您保证会得到一个以 null 结尾的字节字符串,其中只有一个字符CHAR_BIT因为它至少为 8。 即值 65 不可能不适合单个char

也许你的机器有sizeof(char) == sizeof(int)(在这种情况下,endianess无关紧要(,number之后的内存是一个空字符,这只是巧合,再次构建一个看起来像以null结尾的字节字符串的东西。我说看起来像是因为只有当您被允许读取终止空字符时,它才真正是一个。由于在大多数系统上CHAR_BIT是 8(POSIX 要求(,并且由于标准要求int至少为 32 位,因此您的机器极不可能sizeof(char) == sizeof(int)