数组名与指针2

指针与数组名2
1,方括号运算符[ ]。
在定义数组的时候就不说了,就是开辟一片连续的空间,数组名是首地址,是常量。
在调用数组元素时用的是方括号,例如int a[5]; a[1]=2; 在a[1]=2;这个语句的实质是*(a+1)=2; 所以方括号的作用是将前面的和括起来的相加再做间访(间接访问)操作,因此a[1]=2;等价与1[a]=2;不过不建议用后者。知道了方括号的实质,我们就比较容易理解int a[5];int p=a; p[1]=2;了p是指针,因为p[1]=2;与(p+1)=2;等价,所以把指针当数组名这样用是可以的。不过像int a;int *p=&a; p[1]=2;虽然也能够访问到a的后面几个内存空间,但是这些空间并没有分配给这个程序 ,所以这是非法操作,也就是指针越界了。
2,数组名。
我们常常说数组名是地址常量或者说是指针常量。首先数组名肯定不是变量,程序没有专门为这个标识符专门开辟空间,我们也无法给数组名赋值,这都说明数组名不是变量。但数组名具有普通常量不具有的性质,我们无法给普通常量取地址,printf("%p",&1);是错误的,int a[5];printf("%p",&a);却是正确的。即使我们给普通常量转换类型& (int *)1,&(int *[5])1,&(int *)0x1234abcd都是错误的。其实我们可以联想到const限制定义的那种"常量",const int A=1;A是常量,但是接着int m[A];在一些编译器会报错,这说明A不同于普通常量。
3,指针数据类型
指针不管是什么类型,它总只占4字节,所以指针的类型是做什么的呢?指针的类型是说明这个指针指向多少空间,通俗的说就是这个指针管多大的一片空间,指针变量存放的数据就是这连续一片空间的首地址。char *管1字节,int *管4(32位)字节,这样可以得出int *[5]管20字节,因此int a[5][5];int (*p)[5]=a;p+1存的地址比p存的地址正好大20。所以我们可以这样说,int *指向int型变量,int *[N]指向长度为N的int型一维数组。
4:综合
int a[5][5];a的类型是int *[5],a[0]的类型是int *,a和a[0]的值都是数组首地址,但它们数据类型不同。&a[0]得到的是a,严格的说这里&不能称之为取地址,因为a[0]作为一个常量没有自己的存储空间 ,也就没有这个空间地址的说法,&给数组名取地址更像是一种数据类型的升级,int *升级成int *[N],而值不变。相印给数组指针间访就像类型降级,值不变类型变。经过测试发现int a[3][5];a[0]的类型是int *,a和&a[0]的类型是int *[5],还可以继续升级,&a的类型是int *[3][5],不过再不能升级了,因为这个数组没有第三维。
在函数参数传递数组其实就是传递指针,传递一维数组void aa(int p[]);方括号里不需要加数组大小就是因为p是int *型指针变量,不需要什么数组。传递二维数组时,void aa(int p[M][N]);中不需要M,p[][N]就可以因为p是int *[N]型指针变量,与M无关。

猜你喜欢

转载自blog.csdn.net/qq_41260042/article/details/78976971