标签:
一维数组
一维数组例如:int a[5]={0};
数组实际上是一种构造类型,是内存的一段连续的存储区域。
其中int指明了内存访问方式,包括元素的类型,每次跳跃的步长;
其中5指明了构造类型中数据元素的个数,也就是说指明了数组访问时候的可偏移的范围;
其中a有两重含义:
1).作为数组名,a表示一种构造数据类型,这也就是为什么 sizeof(name) == sizeof(type [N])。
2).作为数组名,访问成员时它是首元素的地址 name[i] == *(name+i) == i[name]。
其中{0},表示部分初始化,这样写代表把第一个元素初始化为0,当我们部分初始化时候,没有被我们初始化的元素自动初始化为0,而不是说我们{0}就把全部的元素初始化为0,若是{10},也就是第一个元素10,其他元素自动为0.
对于数组可做如下理解:
类型:type [N]
定义:type name[N]
大小:sizeof(type [N]) 或 sizeof(name)
但是当我们 做这样的定义:int *p=name;或者把数组作为参数传递到函数中时,这个时候再求sizeof(p)的大小就仅仅是当前系统下一个指针类型的大小了(32位系统指针类型大小为4个字节,64为系统指针类型为8个字节)。若是在数组定义的区域内对数组名求sizeof()的到的就是整个数组在内存中所占空间大小。
为什么非要是a[0]开始呢?[ ]可以理解为基址变址运算符,对于a[0]来说,a是基址,0是偏移量,合起来就是变址,a[0]等价于*(a+0),由于a代表首元素的地址,所以只有当a偏移0个单位才可以访问到首元素,所以必须是a[0]开始。基于以上原理,其实 a[i] 可以写成 i[a],它依然等价于*(a+i)。
C语言不允许数组越界,但是自己不做越界检查,要程序员自己做越界检查,所以要是访问越界,那结果将是没有定义的,会造成不可预知的错误。
一维数组名,本质上是一个一级指针,但是对一维数组名做 & 运算,得到的是一个数组指针,而不是一个二级指针。
int array[10];
int (*p)[10]=&array;//这是正确的
int **p=&array;//这是错误的
可以通过一级指针修改0级指针的内容,可通过N级指针修改N-1级指针的指向,总结起来还是一句话,通过指针可以修改它所指向的内容。
下面是一下大小还有跳跃幅度的大小比较程序:
1 #include <stdio.h> 2 int main(void) 3 { 4 //对于一个普通的int型变量 5 int a; 6 printf("&a=%p\n",&a); 7 printf("&a+1=%p\n",&a+1); 8 int *p = NULL; 9 printf("p = %p p +1 = %p\n",p,p+1); 10 /* 11 * &a+1比&a大4,原因是&a是一个int *类型,每次跳跃步长是4个字节, 12 * 相应的一个char类型的则每次跳跃1个字节 13 */ 14 int array[10]; 15 printf("array = %p\n",array); 16 printf("array +1 = %p\n",array+1); 17 /*后者比前者大4*/ 18 printf("&array = %p\n",&array); 19 printf("&array+1 = %p\n",&array+1); 20 /*后者比前者大10*4=40,&array表示一个指向 10个int 的数组指针*/ 21 printf("&array[0] = %p\n",&array[0]); 22 printf("&array[0] +1 = %p\n",&array[0]+1); 23 /*后者比前者大4*/ 24 return 0; 25 }
二维数组
二维数组本质上也是一维数组,只是数组成员由基本数据类型变成了构造数据类型(一维数组)。
定义形式:type name[m][n];其实等价于type[n] name[m],可以这么理解。一维数组的部分初始化和清零依然适用于二维数组。
访问概念辨析:
a表示第0行的首地址,a+i表示第i行的首地址。
*(a+i) 等价于a[i] 等价于&a[i][0],表示第i行第0个元素的地址;
*(a+i)+j 等价于a[i]+j 等价于&a[i][j],表示第i行的第j个元素的地址;
*(*(a+i)+j) 等价于*(a[i]+j) 等价于a[i][j],表示第i行的第j个元素;
二维数组在内存中开始连续的一维空间,所以依旧可以把二维数组当成一维数组来访问,但是需要强制转化:
1 #include <stdio.h> 2 int main() 3 { 4 int array[2][3] = {9,8,7,6,5,4}; 5 int i,j; 6 for(i=0;i<2; i++) 7 { 8 for(j=0;j<3;j++) 9 { 10 printf("%d ",array[i][j]); 11 } 12 putchar(10); 13 } 14 int *p = (int *)array; 15 for(i=0; i<6;i++) 16 { 17 printf("%d ",p[i]); 18 } 19 return 0; 20 }
相应的也可以把一维数组当二维数组来使用,但是这个也需要强制转换,如:int (*p)[2]=(int (*) [2])array;其中array是一维数组名。
如何传递一个二维数组到函数中,例如有二维数组:int a[3][4];则接收它的函数参数是 function(int (*p)[4], n);
二维数组中一些地址间的差异辨析:
1 int main(void) 2 { 3 int a[3][5]={0}; 4 int *p=(int *)a; 5 printf("%d\t,%d\n",sizeof(a),sizeof(p));//60 8 6 printf("&a[0]=%p,&a[0]+1=%p\n",&a[0],&a[0]+1);//相差20=5*4 7 printf("a=%p\t,a+1=%p\n",a,a+1);//相差20=5*4 8 printf("&a=%p\t,&a+1=%p\n",&a,&a+1);//相差60=5*4*3 9 return 0; 10 }
二级指针比较典型的是用二级指针管理二维空间
标签:
原文地址:http://www.cnblogs.com/luojialin/p/4782318.html