对 C++ 中的 char* 感到困惑

Confusing about char* in c++

测试代码:

#include <iostream>
using namespace std;
int main()
{
    const char* b="str";
    cout << b << endl;
    cout << *b << endl;
    cout << &b << endl;
    cout << *(&b) << endl;
    
    
    return 0;
}

结果:

str
s
0x7ffdf39c27f0
str

我 运行 我的代码在网上 runoob online compiler

为什么我会得到这些结果?我看了一些关于 char* 的问题,但还不足以让我理解。有人可以向我解释一下吗?图片最好。

我想通过推荐的书籍或博客进一步了解它。

顺便说一句,使用char b[]而不是const char*,我得到了相同的结果。


非常感谢大家。

我只想知道为什么 char 指针的值不是地址。

我认为地址类似于 0x7ffdf39c27f0。内存地址。

但是const char* b = "str"。 b 只是 str.

而且我发现 *b*("str") 相同。

所以我想知道内存中发生了什么?为什么 char 指针的值不是地址?

cout << b << endl;

您正在打印字符串 b

cout << *b << endl;

你打印的是指向b第一个字符的指针,所以等同于:

cout << b[0] << endl;
cout << &b << endl;

&bb的内存地址,也就是电脑中存放b的地址内存。

cout << &b << endl;

因此,您在此处打印 b 的内存地址。电脑把b存储在内存地址0x7ffdf39c27f0中,这样就得到了

cout << *(&b) << endl;

您正在打印一个指向 b 内存的指针,因此您打印变量 b 的内存地址处的值,这与

相同
cout << b << endl;

编辑:一个指针包含一个 地址,它(通常,它可以指向一个函数,例如)表示一个对象的位置,并打印一个指针(通常) 打印该内存地址的 value。因为 char * 与以 null 结尾的字符串密切相关,所以有一个特殊的字符指针重载来打印指向的字符串。

指针变量仍然是一个变量,并且有自己的地址,所以 &b 导致指向指针的指针,在这种情况下是 char **,因为它不再是a char *, cout << &b; 打印 b 的地址,而不是 b 指向的地址或 b.

指向的字符串

要了解代码输出的内容,您需要了解 C++ 输出流(类型为 std::ostream 的对象),因此对象(例如 std::cout)有许多重载operator<<() 个。调用的重载取决于提供的参数类型。

我将解释你的第二个例子,但对第一个例子的解释几乎相同。

const char* b="st[=10=]r";
cout << b << endl;
cout << *b << endl;
cout << &b << endl;
cout << *(&b) << endl;

cout << b 扩展为 cout.operator<<(b),其中 b 的类型为 const char *。运算符函数的重载假定参数指向一个以 nul 结尾的字符串(的第一个字符),该字符串在内存中表示为 char 的数组,该数组以 char 结尾,值为 '[=20 =]'(零)。 operator 函数输出它找到的每个字符,直到它到达 '[=20=]' 个字符。找到的第一个 '[=20=]' 是您在 't' 之后明确插入的那个,因此会产生输出 st。事实上,你的字符串在 'r' 之后有第二个 '[=20=]' 是无关紧要的,因为运算符函数在它找到的第一个停止。

cout << *b 扩展为对 operator<<() 的不同重载的调用,它接受单个 char,并输出 char*bb表示的字符串中第一个字符的值。于是产生了输出s.

cout << &b 中,&b 具有类型 const char ** 或(等效)char const **。没有接受 const char ** 的输出流 operator<<() 的重载,但是有接受 const void * 的重载。由于任何指针(指向成员的指针或指向函数的指针除外)都可以隐式转换为 void *,该转换是(由编译器)执行的,因此重载匹配并被调用。 operator<<() 的特定重载打印内存中的地址。

第三种情况下的隐式转换在前两种情况下不会发生,因为不需要隐式转换的调用比需要隐式转换的调用更匹配。

在最后一个语句中 *(&b) 等同于 b。之所以如此,是因为 & 是此代码中的寻址运算符,而 * 是取消引用运算符(它是寻址运算符的逆运算)。所以最后一条语句产生与 cout << b.

相同的输出