数组和指针是两种不同的类型,数组具有确定数量的元素,而指针只是一个标量值。数组可以在某些情况下转换为指针,当数组名在表达式中使用时,编译器会把数组名转换为一个指针常量,是数组中的第一个元素的地址,类型就是数组元素的地址类型;
指针的本质是一个与地址相关的复合类型,它的值是数据存放的位置(地址);数组的本质则是一系列的变量;
数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。指针可以随时指向任意类型的内存块,它的特征是"可变",所以我们常用指针来操作动态内存;
当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针;
例1:
int main(int argc, char* argv[]) { int a[5] = {1,2,3,4,5}; int *p1 = a + 1; int *p2 = (int *)(&a+1)-1; cout << *a << " " << *p1 << " " << *p2 << endl; }
输出结果为:1 2 5
解释:数组名代表数组的首地址,*a即为数组中第一个元素的值1; p1为首地址加1,指向第二个元素,输出2;而*p2 = (int *)(&a+1)-1; a代表数组的首地址,而&a是数组的指针,&a+1代表以a为首地址,偏移一个数组大小(这里是5个int的大小),(int *)(&a+1)指向数组的第六个元素,(int *)(&a+1)-1;指向数组的第五个元素,因此输出是5.
例2:
int a[5]={0,1,2,3,4};
数组名a若出现在表达式中,如int *p=a;那么它就转换为第一个元素的地址,等价于int *p=&a[0];
int aa[2][5]={0,1,2,3,4, 5,6,7,8,9};
数组名aa若出现在表达式中,如int (*p)[5]=aa;那么它就转换为第一个元素的地址,等价于int (*p)[5]=&aa[0];
aa[0]的类型是int [5],是一个元素数量为5的整型数组,就算转化,那么转化成的是数组(int [5])中第一个元素的地址&aa[0][0],类型是 int *。所以,要么是int (*p)[5]=aa;要么是int (*p)[5]=&aa[0];
例3:
int *p[n] :指针数组,每个元素均为指向整型数据的指针 int (*p)[n] :p为指向一维数组的指针,这个一维数组有n个整型数据 int *p() :函数返回指针,指针指向返回的值 int (*p)() :p为指向函数的指针 int *p[3][4] :一个3*4的数组,每个元素是指向int的指针 int (*p)[3][4] :一个指针,指向3*4的int数组 int (*p[3])[4] :一个具有3个元素的数组,每个元素是一个指向具有4个元素的int数组的指针