引言
这篇文章探讨的内容是由李炅同学和我的讨论产生的,在此之前我对一些问题也不甚了了,多方查阅资料后,我在此做出总结,与大家共同学习。
首先,我们从两个简单的问题开始。
(注:本文详细叙述了探究过程,若嫌太长可直接看总结部分)
两个问题
一维数组的数组名是指针吗?
你可能会说:是的(实际上某些书中甚至也是这么说的)。众所周知,如果我们使用如下语句:
int a[3];
cout << a; //这里使用了C++的输出语句,相信大家可以望文知义
输出结果是一个地址,而且,如果我们定义一个指针p,并执行p=a
,也可以正常执行。这不都说明了数组名a本身就是一个指针吗?
然而,事实并非这么简单,让我们使用以下语句查看a与p的数据类型。
int a[3];
int* p;
cout << "type of a is: " << typeid(a).name() << endl;
cout << "type of p is: " << typeid(p).name() << endl;
得到的输出结果是:
type of a is: A3_i
type of p is: Pi
上述结果含义为:
a的类型为 int [3] ,是一个有3个元素的int型数组 p的类型为 int* ,是一个指向int型变量的指针
既然类型不同,为什么可以进行p=a
的赋值操作呢?这是因为, int [N] 可以经过类型转换,变为 int* 类型。当我们执行类似a+0
的操作(获取数组某个元素的地址)时,实际上就进行了隐式类型转换将其转换为指针,我们可以进行如下测试:
cout << "type of a+0 is: " << typeid(a+0).name() << endl;
得到结果:
type of a+0 is: Pi
综上,数组名并非指针类型,但可以被转换为指针。
一维数组可以作为参数传入函数吗?
答案似乎又是显而易见的:可以!因为我们很早之前就学过数组作为参数。为了验证这一点,我们不妨尝试如下程序:
void output_size(int a[]){
cout << "---output_size---" << endl << sizeof(a) << endl;
return;
}
int main() {
int a[3];
cout << "---main---" << endl << sizeof(a) << endl;
output_size(m);
return 0;
}
输出结果:
---main---
12
---output_size---
4
这真是匪夷所思!好端端的一个数组,为什么传参之后大小就变了呢?原来,当数组作为参数时,就“丧失了本心”,被转换为一个指针,因此在output_size()
函数中sizeof(a)
返回的实际上是一个指针的长度,而不是数组的长度。
细心的读者可能会发现问题:在sizeof(a)
中,a也是作为sizeof()
函数的一个参数,为什么没有被转换为指针呢?实际上,这是一个仅有的特例,因此,我们可以进行如下总结:
当数组作为参数时(作为sizeof()
的参数除外),会自动被转换为指针。
二维指针与二维数组
未完待续……
总结
- 数组名并非指针类型,但可以被转换为指针。
- 当数组作为参数时(作为
sizeof()
的参数除外),会自动被转换为指针。
对于如下定义:
int a[3][4];
表达式 | 类型 | 类型解释 | 备注 |
---|---|---|---|
a | int [3][4] | 二维数组,3行4列 | 可被转换为行指针 |
a+0 | int (*)[4] | 行指针(数组指针) | 指向一个有4列的数组 |
*(a+0) | int [4] | 数组,4列 | 可被转换为列指针,等价于a[0] |
*(a+0)+0 | int * | 列指针 | 指向一个元素 |
*(*(a+0)+0) | int | 等价于a[0][0] |
未完待续……