【原创】学习笔记:二维数组与指针的指针

来源:互联网 发布:渮泽淘宝托管公司 编辑:程序博客网 时间:2024/04/28 10:23
【原创】二维数组与指针的指针

最近因为论文的关系又开始使用起原始,强大但也很复杂的C语言写程序了,当然也就又遇到了这个看似简单实际复杂的老问题,花了点时间去回忆。网上有关这个问题的文章挺多,但是能说的比较清楚的寥寥无几。既然这样就自己总结一下吧。
一维数组和指向该数组的指针很好理解,也非常实用,这里就不多说了。二维数组和指针的指针,这两个概念看起来和一维的逻辑差不多,只不过多了一层逻辑而已。这样想你就错了,实际他们之间有很大的差别。

闲话少说,这里先讨论一下以下3个概念:
(1) int **ptr;
(2) int *ptr[ 5 ];
(3) int (*ptr)[ 5 ];
        以上3个例都可以表示整数的二维数组,在使用不同的赋值方法后都可以实现 ptr[ 1 ][ 1 ] 的方式访问其内容;但它们的差别却是很大的。它们本身都是指针,它们的最终内容都是整数。比如你写 ptr[ 0 ],对于三者来说,其内容都是一个整数指针,即 int *;ptr[ 1 ][ 1 ] 这样的形式才是其最终内容。

所代表的含义(这里抽象假设2维数组是一个表的形式,由行和列组成):
(1) int **ptr1:ptr1是一个 指针的指针,可以指向一个或 "一组"(有规则排列的)整数型指针(的首地址)。当他指向一组整数型指针的时候
(ptr1+1)的增量是,用于存放一个整数型指针所占内存空间的字节数(32位平台是4字节)。这种指针只能一直在同一个维度上移动。实际**ptr1的含义只不过就是实现两次引用(跳转)而已。

(2) int *ptr2[ 5 ]:是定义一个指针数组,成员是5个整数型指针,ptr2是指向这组指针首地址的指针,这里的ptr2和(1)中ptr1实际是相同的,(ptr2+1) 表示指向下一个数组成员的,增量也是,用于存放一个整数型指针所占内存空间的字节数。实际ptr2就是一维数组。

(3) int (*ptr3)[ 5 ]:是定义一个指针ptr3,他指向一个含有5个元素的一位数组的首地址,与上两个不同。(ptr3+1) 表示指向下一个一位数组,而它的增量是,用于存放一个整数型变量所占内存空间的字节数x5,而恰好这个ptr3才是和我们最常见代码 int arr[3][5]  中的这个arr的结构是相同的。这种指针可以在2个维度(纵向或横向)上移动。举个例子就比较清楚了:

以下两行代码是合法的:
    int *ptr, arr[5];    //在声明中ptr 和 arr 是相同结构的
    ptr = arr;           //所以在这里能用等号连接

在这里 (*ptr) == arr[0] 都表示arr数组的第一个元素的内容;
所以 在两边各加上一个维度(*ptr)[5] == arr[3][5]后ptr和arr的结构还是相同的。注意:这里新增的维度不是[5]而是[3]。
由此推出以下代码也是相匹配的:
    int **p, (*ptr)[5], arr[5];
    ptr = &arr;        //ptr 指向的是arr 但是这里 (ptr+1) 是没有意义的,因为不存在有效的下一个“行”。
    *p = arr;
    //p = &arr;         //这里是错误的,因为p只能在一个维度上移动
                            //虽然在这里只有一个有效维度,第二个隐藏的维度只不过是零而已

在增加了第二个有效维度后就理解也是相同的,代码如下:
    int arr[3][5], **p, (*ptr)[5];
    ptr=arr;
    //p = ptr;        //出错原因和上边相同
    //p = arr;        //出错原因和上边相同

再看下边这段代码:
    int arr[3][5], *ptr[5], **p;
    for (int i=0; i>3; i++)  ptr[i] = arr[5];       //ptr中存放了arr数组每一行的首地址
    p = ptr;           // p只需要在纵向移动,横向实际是ptr负责的,p只是实现两次引用(跳转)
原创粉丝点击