如果我执行以下代码:

#include<iostream>
using namespace std;

int main(){
    char str[20] = {'a','b','c','d','e'};
    cout<<str<<endl;
    return 0;
}

它输出abcde,但是如果我执行以下代码:
#include<iostream>
using namespace std;

int main(){
    int arr[20] = {1,2,3,4,5};
    cout<<arr<<endl;
    return 0;
}

它输出0x7fff22eecc30,我尝试在两个不同的在线编译器中执行此代码,并且它们给出相同的输出。

char array中,它返回数组内容,但在int array中,它返回内存地址。这是为什么?另外,两个不同的在线编译器如何返回相同的内存地址?

我已经尝试过在线查找此内容,但不确定要查找什么?

最佳答案

std::cout知道如何打印

在后台cout是从basic_ostream类模板派生的对象。标准库提供了一些函数,这些函数告诉basic_ostream如何打印不同类型的数据。 (有些是成员函数,有些不是-但这在这里并不重要。)

这里有些例子:

basic_ostream<charT,traits>& operator<<(bool n);
basic_ostream<charT,traits>& operator<<(short n);
basic_ostream<charT,traits>& operator<<(int n);
basic_ostream<charT,traits>& operator<<(double f);
... and more ...

这些函数告诉cout(和其他基本输出流)如何打印bool,短裤,整数等。

还有这两个
basic_ostream<charT,traits>& operator<<(const void* p);

template<class traits>
    basic_ostream<char,traits>&
    operator<<(basic_ostream<char,traits>&, const char*);

第一个告诉cout如何打印无类型指针的地址(void*)。

第二个用于打印C样式的字符串,尤其是源代码中的文字字符串。例如cout << "Hello";
数组呢?

标准库不提供对打印数组(或任何其他集合)的任何直接支持。如果要打印集合,则必须确定该集合所需的格式,然后自己编写代码。

这对于结构和类是相同的。如果定义自己的类,cout不知道如何打印---您必须自己编写代码。

为什么第一个示例输出“abcde”?

您正在尝试打印char[20](字符数组)。 basic_ostream没有数组的重载<
但是BUT-C++允许将“T的数组”隐式转换为“T的指针”,因此您的str变量是从char[20]隐式转换为char*。这与我上面列出的最后一个重载相匹配-应该用于C风格的字符串。 (其他答案已经讨论了有关C字符串应该具有的终止零的问题。)

那第二个例子呢?
arr的类型是int[20]。再次,cout不知道如何打印数组。

SO-C++尝试将您的int[20]隐式转换为int*。但是int*没有重载,因此C++会再次尝试。它隐式地将int*转换为void*(允许这样做)-现在找到一个匹配项。
void*重载输出指针的内存地址。

charsigned charunsigned char的数组外,所有其他数组均会发生这种情况。 T的数组向下转换为指向T的指针,T向下转换为一个空指针。

为什么char*与其他任何指针类型区别对待

因为我们经常打印C风格的字符串(尤其是字符串文字)。喜欢,很多很多。

09-30 17:47
查看更多