对 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;
&b
是b
的内存地址,也就是电脑中存放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
。 *b
是b
表示的字符串中第一个字符的值。于是产生了输出s
.
在 cout << &b
中,&b
具有类型 const char **
或(等效)char const **
。没有接受 const char **
的输出流 operator<<()
的重载,但是有接受 const void *
的重载。由于任何指针(指向成员的指针或指向函数的指针除外)都可以隐式转换为 void *
,该转换是(由编译器)执行的,因此重载匹配并被调用。 operator<<()
的特定重载打印内存中的地址。
第三种情况下的隐式转换在前两种情况下不会发生,因为不需要隐式转换的调用比需要隐式转换的调用更匹配。
在最后一个语句中 *(&b)
等同于 b
。之所以如此,是因为 &
是此代码中的寻址运算符,而 *
是取消引用运算符(它是寻址运算符的逆运算)。所以最后一条语句产生与 cout << b
.
相同的输出
测试代码:
#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;
&b
是b
的内存地址,也就是电脑中存放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
。 *b
是b
表示的字符串中第一个字符的值。于是产生了输出s
.
在 cout << &b
中,&b
具有类型 const char **
或(等效)char const **
。没有接受 const char **
的输出流 operator<<()
的重载,但是有接受 const void *
的重载。由于任何指针(指向成员的指针或指向函数的指针除外)都可以隐式转换为 void *
,该转换是(由编译器)执行的,因此重载匹配并被调用。 operator<<()
的特定重载打印内存中的地址。
第三种情况下的隐式转换在前两种情况下不会发生,因为不需要隐式转换的调用比需要隐式转换的调用更匹配。
在最后一个语句中 *(&b)
等同于 b
。之所以如此,是因为 &
是此代码中的寻址运算符,而 *
是取消引用运算符(它是寻址运算符的逆运算)。所以最后一条语句产生与 cout << b
.