int和char数组有什么区别?

6
下面是“int数组”和“char数组”的区别:
int数组保存整数值,每个元素占用4个字节的内存空间。char数组保存字符值,每个元素占用1个字节的内存空间。
int main()
{
    int numbers[] = {2,1,3};
    char letter[] = {'a','b','\0'};
    cout<< numbers<<endl;
    cout<< letter<<endl;
}

输出:

0x22ff12 // an address
ab

为什么 213 没有显示出来? 我知道数组的名称会指向其第一个元素的地址,但为什么 char 数组表现出不同的行为?


4
在C语言中,数组在大多数情况下会衰变为指向其第一个元素的指针...但是cout<<endl不是C语言中识别的元素。 - pmg
嗯...我的意思是:在C语言中,<<是按位左移运算符,不能与未识别的语言元素一起使用 :) - pmg
这个回答解决了你的问题吗?cout << 使用char*参数打印字符串,而不是指针值 - xskxzr
10个回答

11

没有直接接受数组类型的 operator<< 重载函数,所以你传递的参数(例如 numbersletter)会被转换为指向 void*char* 的指针。

有一个可以接受 const void*operator<<() 重载函数,还有一个可以接受 const char* 的重载函数。当你调用:

cout<< numbers<<endl;

匹配的是const void*版本,但当你调用时:

cout<< letter<<endl;

const char* 版本匹配成功。

const void* 版本中,指针被显示出来,而在 const char* 版本中,字符串被显示直到空终止符。


9

当您使用cout打印数组时,它将打印出数组的基地址。

例外情况是对char数组进行了重载,以将其打印为c字符串。

如果您想要打印int数组的元素,则需要逐个元素进行打印。


6
原因是operator<<被重载为const char*,它打印每个字符直到遇到\0为止。
没有对应于int[N]的重载,可以打印其中的每个元素。相反,当您写cout << numbers时,它调用了重载为void*operator<<,它打印地址。
但是,如果您为T[N]重载operator<<,那么您也可以像这样打印它。
下面是一个简单的示例:
template<typename T, size_t N>
std::ostream & operator<<(std::ostream & out, const T (&a)[N])
{
   for(size_t i = 0 ; i < N ; ++i)
      out << a[i] << ' ';
   return out;
}

int main()
{
   int numbers[] = {2,1,3};
   char letter[] = {'a','b','\0'};
   cout<< numbers<<endl;
   cout<< letter<<endl;
}

输出:

2 1 3 
a b

Demo : http://ideone.com/O4T9N


4
在C语言中,因此在C++中,字符串通常由以0结尾的字符数组表示。因此,为std::ostream类提供了一个重载的operator<<运算符,其中std::cout是一个实例,它将char*打印为字符串。没有这样常见的int数组用法,也没有任何约定,因此操作员会“知道”要输出多少个元素,因此将数组指针与输出任何其他指针的operator<<版本匹配,并打印其地址。

+1 因为这正是我想写的。但如果您能显示这两个重载函数的具体函数原型,那将会很有教育性(=有帮助)。 - Konrad Rudolph

3

char数组很特殊,因为有一个重载的运算符<<,可以将其内容显示为字符串。

所有其他数组默认情况下都将显示地址。


1
在C/C++中,数组实际上是指向第一个元素的指针。指针保存值存储的地址。因此,如果您打印指针数字,您将获得内存中存储第一个值(2)的地址。
char*是一个例外,当您尝试打印它时,它将表现为字符串。

2
数组不是指针;它们在许多情况下会衰变成指针,但这并不意味着它们是同一种东西。 - dlev

1

你的代码主要是关于 C 语言的。在 C 语言中,char 数组是字符串的事实标准表示形式。另一方面,在 C 语言中,数组也是指向内存单元(即数组第一个元素的地址)的指针。

因此,当你打印出字符数组时,实际上你打印出了一个字符串(因为 C 语言将其视为字符串)。而当你打印出整数数组时,你实际上打印出了数组第一个元素的地址。


0

字符数组包含字符。
它可以像这样初始化:

char arr[4]={'a','b','c','\0'};
char arr[4]={"abc"};

一个整数数组包含整数。
它可以像这样初始化:
int arr[4]={1,2,3,4};  

0

numbers是一个指针。在C++中,所有的数组实际上都是指针,numbers[3]只是意味着“在内存地址&number+3处的值”,因此您正在输出numbers中第一个元素的内存地址。


0

编译器没有理由知道你的int[]数组在哪里结束,但传统和标准库规定C字符串是以空字符结尾的char[]数组。对于以空字符结尾的int[]数组,没有这样的传统或库支持。

如果您需要此功能,可以使用C++ 漂亮打印机模板。我模糊地记得,当类型实际上知道边界时,一个数组的边界会被使用,即使您使用[]而不是[3],您的代码仍然无法工作。

只是提供信息,您的代码不能通过在STL中用[3]替换[]来修复,尽管也许可以重载operator<<


在使用C数组边界作为模板参数时需要谨慎:http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=%2Fcom.ibm.vacpp7l.doc%2Flanguage%2Fref%2Fclrc16deduct_non-type.htm - Jeff Burdges

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接