Cout < < with char * 参数打印字符串,而不是指针值

这个:

const char * terry = "hello";
cout<<terry;

打印 hello而不是 'h'的内存地址。为什么会发生这种情况?

125208 次浏览

您应该将您的代码更改为:

cout << static_cast<const void*>(terry);

问题是,对于指向 C 样式字符串以打印字符串内容的指针,<<运算符被重载。如果将其强制转换为原始指针,那么将具有使用 iostream 打印指针的默认行为。

“ hello”是一个字符串,也就是字符数组。const char*是一个指向这个数组的指针,因此当您取消引用这个指针时,将得到第一个元素的值。

就好像

int a[] = {1, 2, 3};
int *b = a;
cout << *b << endl;

你只能打印 1

原因是 std::coutchar *视为指向 C 样式字符串(第一个字符)的指针,并将其作为指针打印出来。如果你想要的是 地址,你可以直接把它转换成 不是这样处理的指针,比如:

cout << (void *) terry;

(或者使用 const void *强制转换,如果您担心抛弃常量,这在本例中不是问题)。


如果你是一个纯粹主义者而不是实用主义者,你也可以使用 C + + static_cast,如下所示:

cout << static_cast <const void *> (terry);

尽管在这种情况下没有必要,但是对 void *的强制转换可以很好地工作。下面的示例代码显示了所有这些操作选项:

#include <iostream>
int main (void) {
const char *terry = "hello";
std::cout << terry << '\n';
std::cout << (void *) terry << '\n';
std::cout << (const void *) terry << '\n';
std::cout << static_cast<const void *> (terry) << '\n';
return 0;
}

输出(地址在您的环境中可能不同) :

hello
0x8048870
0x8048870
0x8048870

请注意,在使用 static_cast时,您应该确保不要尝试抛弃 static_cast <void *>的常量(这就是 const_cast的用途)。这是较新的 C + + 强制转换所做的检查之一,而旧式强制转换没有这个限制。

cout是重载的,因此当您给它一个 char*时,它将作为指向 C 样式字符串的指针打印。因此,它打印出字符,直到遇到一个空终止字符。

如果使用 printf而不是 cout,您将看到地址。您还可以将指针强制转换为另一种类型,比如 (void*),您还可以获得地址。

std::cout上的 <<操作符被重载。它的行为取决于正确操作数的类型。(它实际上是几个不同的函数,全部命名为 operator<<; 编译器决定调用哪个函数。)

如果给它一个 char*const char*,它将操作数作为指向 C 样式字符串(第一个字符)的指针,并打印该字符串的内容:

const char * terry = "hello";
cout << terry; // prints "hello"

如果给它一个 char值,它会将该值打印为一个字符:

cout << *terry;   // prints "h"
cout << terry[0]; // the same

如果给它一个类型为 void*的指针,它将输出该指针值(以某种实现定义的方式,通常是十六进制) :

cout << static_cast<const void*>(terry); // prints something like 0x4008e4

char*const char*作为指向 C 样式字符串的指针是一种特殊情况,并且是唯一一种(我能想到的)导致 operator<<打印操作数值以外的内容的情况。其原因可以追溯到 C + + 在 C 中的根,它没有“ string”类型,并且通过 char*指针操作字符串。

对于 operator<<、各种整数和浮点数字类型、 std::string等等,还有许多其他重载。

std::cout定义为 std::ostream这个定义为 operator<<

值得注意的是这句话:

template< class CharT, class Traits >
basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os,
const char* s );

当使用带有 char*类型参数的 <<时,将选择此选项。

任何其他非字符指针类型的情况是 给你:

basic_ostream& operator<<( const void* value );

这继续到 std::num_put,它是用来格式化数值的。因此,在 C 格式化函数中,指针的数值解释类似于 %p