二维数组和指针

来源:互联网 发布:移动大数据平台 编辑:程序博客网 时间:2024/06/03 20:19

0.

关于C语言的指针,我觉得真正难的是:当指针和二维数组掺和起来的时候,太令人肾疼了。如果你不是很清楚一维指针,不要看这篇文章!!!这篇文章中写的都是我对二维数组和指针的理解,并没有真正可靠的出处。

1.正式开始

对二维数组(int a[3][4])的理解
(0). 二维数组中有很多看起来一样,但所包含的意义不一样的东西,煞是蛋疼,注意区分。

(1). 从二维数组的角度来看,a代表二维数组首元素的地址,
对二维数组来说,它的首元素不是一个简单的元素了,而是由4个整型元素构成的一维数组。 (这个时候把一维数组看成一个元素)
所以a是第一个一维数组的地址,a+1是第二个一维数组的地址。

(2). 二维数组可以理解为数组的数组,把每一行看成一个一维数组。
a是二维数组名,a中有3行,即3个行元素,a[0],a[1],a[2],每一个行元素是一个一维数组。
所以可以把a[0]理解为一个一维数组的数组名(也就是这个一维数组的首元素地)。
那么a[0]+1是二维数组0行1列的那个元素的地址,a[0]与&a[0][0]等价,a[0]+1与&a[0][1]等价就很容易理解了。(在一维数组的层面去理解上面的问题)
特别注意:在二维数组a中,a[i]不代表某一元素的值,它代表的是一个一维数组名。

(3). 如果像(2).那样,把二维数组看成一维数组(a[3])。
它的第一个元素是a[0],我们可以通过a[0]或者通过指针的方式去访问第一个元素*(a+0)。
所以*(a+1)和a[1]是等价的。都是访问a[1]这个元素的。这一点也就很容易理解了。
a[0]也是一个一维数组(假设为n[4]),
所以把*(a+0)或者a[0]理解为这个一维数组的数组名n(也就是这个一维数组的首元素地址)。
*(a+0)+1就是n这个一维数组的第二个元素的地址。

(4). 在指向行的指针前面加一个*,就转换成了指向列的指针。
例如,a和a+1是指向行的,前面加个*就是指向列的了
反之,在指向列的指针前面加上&,就变成指向行的了。
例如,a[0]是指向0行0列元素的指针,在它的前面加上一个&,得到&a[0],它指向二维数组的0行
注意:在二维数组中,不要把&a[i]简单的理解为元素a[i]的物理地址,因为并不存在a[i]这样一个实际的数据存储单元。
它只是一种地址的计算方法,得到第i行的行地址。

(5). 上面出现的a,a[0],*(a+0),&a[0][0],&a[0]的值都是相同的,不过所包含的含义是有区别的!!!!!!


2.

上面如果没有理解,或者不赞同的话,不要继续看下去!!!

指向二维数组a[3][4]的指针
有两种方法将指针指向二维数组。
1.int *p;
2.int (*p)[4];
这两种方法的定义,初始化,使用都是有区别的。

  1. int *p;
    这是一个指向一个整型数据的指针,所以我们在初始化的时候,只能把某个整型元素的地址给p。
    例如:
    // p=a; // p=&a[0]; // p=a[0]; // p=*a; // p=&a[0][0];
    //前两个会报错后面三个则不会。
    因为二维数组中的元素也是连续存放的,所以也可以把二维数组a[3][4]看成a[12]这个一维数组,然后就可以像一维数组那样使用p了。

  2. int (*p)[4];
    这个时候p不是指向整型数据的指针了,而是变成了指向一个包含m个元素的一维数组的指针了。
    这个时候p的类型不是int 了,而是int [4]。
    // p=a; // p=&a[0]; // p=a[0]; // p=*a; // p=&a[0][0];
    // 后三个会报错,前两个不会

int (*p)[4]的使用:
1.这个时候p的类型是int *[4],则p++实际上地址是加了16。
2.可以直接通过(*p)[i]去访问p所指向的一维数组的第i个元素
3.也可以通过二级指针的形式去访问其中的元素。
例如:(*p)[i]和 * (*(p)+i)是等价的。

    #include<stdio.h>    int main()    {        int a[2][2]={1,2,3,4};                                              int (*p)[2];        p=a;                printf("%d\n",(*p)[1]);        printf("%d\n", *(*(p)+1) );        printf("%d\n", *(*(p)+3) );        printf("%d\n", *(*(p+1)+1) );        return 0;    }//输出结果是2,2,4,4

附加:

    #include<stdio.h>    int main()    {        int a[4]={1,2,3,4};        int (*p)[4];            //int (*p)[4]也可以指向一维数组        p=&a;        //注意这儿不能写成p=a;        //这个时候a是一维数组,数组名就代表首元素地址,和p的类型不符合        //a前面加&就可以表示行地址了        //这个时候就有点把一维数组扩展成二维数组那样(有行地址有元素地址)的感觉了        printf("%d\n",(*p)[1]);        printf("%d\n", *(*(p)+1) );        printf("%d\n", *(*(p)+3) );        return 0;    }
0 0