C语言之指针与二维数组

    指针,其实就是地址,可以指向一块自己分配大小的空间。数组即是多块一位的空间的线性排布。二维数组,虽然在人文定义的感觉上有了面的理解,但实际在内存中也是一维的线性空间。
    对于讨论二维数组,首先我们应该先讨论一维数组与指针。
    例:int a[3];
           int *p;
           p=a;
    上述的代码段可以经过编译器,可得,p与a的指向类型相等,a是数组a[3]的数组名,也是数组的首地址常量,a=&a[0],a是指针,指类(指向的数据的类型)是int,而p的指类也是int,由于a与p同为指针,但是有点区别,就是a是指针常量,p是指针变量,所以当我们sizeof(a)时,结果为12,当我们sizeof(p)时,结果为4,指针都是四个字节的空间,但是由于a是指针常量,指向的是12个字节大小的数组空间,所以在使用sizeof()时,操作系统也就会根据它的指向空间来获得其指向的大小,而p不是指向空间,是个变量,所以也就是只能是4个字节的空间了。
      a[] <=> *(a),
      a[0], a[1],...a[i] <=> *(a+0), *(a+1), ....*(a+i),
      &a[0], &a[1],...&a[i] <=> a+0, a+1, ....a+i
     由以上例子可知,*对于指针来说就是降阶,&对于指针来说就是升阶,*(a+i)代表的是a[i]的值,而&a[i]代表的是指向a[i]的指针。
     对于一维的数组中的p=a的理解就是,把int当成“数据类型”可得:
         数据类型 a[3];
         数据类型 *p;
         p=a;
     根据上述,p与a指向的类型相同,所以可以赋值,换另一种理解:
数据类型 a[3] 中的中括号相当于*号,在类型声明时,先忽略a[3]数组的大小问题,即 数据类型 a[] ={0},<=> 数据类型 *a ={0},由此我们可以发现p与a的指类都是一样的啦。
由此一维数组的讨论结束。

     二维数组,依旧是一维数组,只是一维数组里面的每一个元素都是一段一维数组。

     【图片】

     对于讨论二维数组的代码如下:


#include <stdio.h>

void fun(int m[3000][4]);

void fun(int m[][4]){
printf("m=%p\nm+1=%p\nm[0]=%p\nm[0]+1=%p\n",
m, m+1, m[0], m[0]+1);
printf("&m[0]=%p\n&m[1]=%p\n&m[0][0]=%p\n&m[0][1]=%p\n",
&m[0], &m[1], &m[0][0], &m[0][1]);
printf("&m=%p\nm+1=%p\n&m+1=%p\n\n", &m, m+1, &m+1);
}

void main(void){
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

printf("a=%p\na+1=%p\na[0]=%p\na[0]+1=%p\n",
a, a+1, a[0], a[0]+1);
printf("&a[0]=%p\n&a[1]=%p\n&a[0][0]=%p\n&a[0][1]=%p\n",
&a[0], &a[1], &a[0][0], &a[0][1]);
printf("&a=%p\na+1=%p\n&a+1=%p\n\n", &a, a+1, &a+1);

fun(a);
}


该程序的结果如下:
a=0019FF10 m=0019FF10
a+1=0019FF20 m+1=0019FF20
a[0]=0019FF10 m[0]=0019FF10
a[0]+1=0019FF14 m[0]+1=0019FF14
&a[0]=0019FF10 &m[0]=0019FF10
&a[1]=0019FF20 &m[1]=0019FF20
&a[0][0]=0019FF10 &m[0][0]=0019FF10
&a[0][1]=0019FF14 &m[0][1]=0019FF14
&a=0019FF10 &m=0019FEC0
a+1=0019FF20 m+1=0019FF20
&a+1=0019FF40 &m+1=0019FEC4
     由于该程序设计到函数的形参的指针传递,与p=a的问题的本质是一样的。
     为什么a的值可以直接复制给m,由上述一维数组讨论可知:
int a[3][4];
int m[3][4] int m[300000][4] int m[][4] int (*m)[4]
a赋值给以上的m,结果两者的指向类型都是一样的,可以做如下理解:
int a[3][4] <=> int[4] a[3],理解为 :数据类型 a[3]
同理可得:
Int m[3][4] <=> int[4] m[3],理解为 :数据类型 m[3]
int m[300000][4] <=> int[4] m[300000],理解为 :数据类型 m[300000]
int (*m)[4] <=> int[4] *m,理解为 :数据类型 *m


     所以在形参中,m的三种声明是等价的,3, 300000, 空,不影响结果。
由于m是变量,&m的值不等于&a的值,a是地址,&a=a,还是首元素的地址,有些人问a的值存放在哪里,对于这个问题,每一次使用数组,对应的a都不是同一个,因为它不是变量,它只是一个立即数,甚至它连常量都不是,使用数组,操作系统就会给我们a的值,所以sizeof(a)里面并没有a的存储空间。
    对于a+1,就是移动一个4*4个字节空间
     a[0]+1,就是移动4个字节空间
因为两者的指类不一样,不在同一阶,a的指类是int[4],a[0]的是int类型
到此,所有讨论完毕。











 

猜你喜欢

转载自blog.csdn.net/sinat_24230393/article/details/50232369