char[] 和 int[] 的区别

Difference between char[] and int[]

所以最近,我看了一个视频,里面说当我定义一个整数数组时

int my_array[] = {1,2,3};

然后我打印 my_array cout << my_array; 然后我会得到内存中第一个整数的地址,但是当我们定义一个字符数组时

char my_string[] = "Hello";

然后当我尝试打印 my_string cout << my_string 它 returns Hello, 类似地 当我们定义一个指向字符的指针

char mystring[] = "HELLO";
char *my = mystring;
cout << my << endl;//HELLO

并且我们尝试打印指针变量它 returns 字符串。

现在读到这个article,我读到字符串带着他的内存地址。但我仍然不明白为什么它们不一样,为什么字符数组打印字符串文字而 int 数组打印第一个的地址。

提前致谢。

my_array would contain the address of the first integer in memory,

没有。 my_array 将包含内存中的三个整数。

if i do cout << myarray << endl then that would print the address of the first item in memory

是的。这就是指定字符流的行为方式。当你插入一个指针时,地址将被打印出来。除非您插入指向 char 的指针,否则会受到不同的处理。

and how is it treated differently?

根据文档,将打印指向的字符及其同级字符,直到到达空终止符为止。

why an array of chars returns the string literal and the int array returns the address of the first one.

我假设 "returns" 这个词的意思是 "print"。

因为non-member std::ostream::operator<<(ostream&, const char *) overload iterates over the memory the char* pointer points to and prints the content of it, while there is no std::ostream::operator<<(int*) overload, so int* is casted to const void* and std::ostream::operator<<(const void*) overload是用来打印值的,那个函数打印的是指针的值

您仍然可以通过手动转换来打印指向字符串的指针的值:

cout << static_cast<void*>(my_string) << endl;

这是 C 的遗留问题,事实上标准库必须支持 C 风格的字符串(char* 以 null 结尾)。为此 std::coutconst char* 进行了重载,将其视为 C 样式字符串并打印到空终止符。

打印地址是将指针传递给 std::cout 的正常行为(因此您的 int 指针内存位置打印输出)。

其实my_array是一个int[3],mystring是一个char[6].

cout << my_string; 打印字符串的原因是应用了这些转换 char[6] -> char const *,并且 ostream operator<< 知道将 char const * 视为 string

对于 cout << my_array,转换为 int[3] -> int * -> void const *void const * 上的 ostream operator<< 只是打印地址。

这个字符数组的声明

char my_string[] = "Hello";

相当于下面的声明

char my_string[] = { 'H', 'e', 'l', 'l', 'o', '[=11=]' };

即数组的元素由字符串文字的字符初始化,包括其终止零。

用于表达式的数组在极少数情况下被转换为指向其第一个元素的指针。

例如,如果您使用 sizeof 运算符,则数组类型的对象不会转换为指向其第一个元素的指针。这是罕见的例外之一。

这是一个演示程序

#include <iostream>

int main() 
{
    int my_array[] = { 1, 2, 3 };
    char my_string[] = "Hello";

    std::cout << "sizeof( my_array ) = " << sizeof( my_array ) << '\n';
    std::cout << "sizeof( my_string ) = " << sizeof( my_string ) << '\n';

    return 0;
}

它的输出是

sizeof( my_array ) = 12
sizeof( my_string ) = 6

但是例如,当数组类型的对象用作运算符 * 的操作数时,它会被转换为指向其第一个元素的指针。

这是另一个演示程序

#include <iostream>

int main() 
{
    int my_array[] = { 1, 2, 3 };
    char my_string[] = "Hello";

    std::cout << "*my_array = " << *my_array << '\n';
    std::cout << "*my_string = " << *my_string << '\n';

    return 0;
}

程序输出为

*my_array = 1
*my_string = H

在 C++ 标准中,定义了重载 operator << 以输出由指向 char 的指针指向的字符串(以零字符结尾的字符序列)。

所以如果你会写

std::cout << my_string << '\n';

然后在这个运算符的调用中 << 字符数组被隐式转换为指向其第一个元素的指针,并输出指向的字符串。

对于整数数组,运算符 << 的定义方式是它只输出数组的地址,即第一个元素的地址。

这是一个演示程序。

#include <iostream>

int main() 
{
    int my_array[] = { 1, 2, 3 };
    char my_string[] = "Hello";

    std::cout << my_array << '\n';
    std::cout << my_string << '\n';

    return 0;
}

它的输出可能看起来像

0x7ffdcfe094e4
Hello

如果你想要一个字符数组,可以选择输出数组地址的重载运算符 << 那么你应该将数组(隐式转换为指向其第一个元素的指针)转换为类型void *.

这里还有一个演示程序。

#include <iostream>

int main() 
{
    int my_array[] = { 1, 2, 3 };
    char my_string[] = "Hello";

    std::cout << my_array << '\n';
    std::cout << static_cast<void *>( my_string ) << '\n';

    return 0;
}

它的输出可能是

0x7ffef7ac0104
0x7ffef7ac0112