相信大家在学习C语言时,对一维数组和指针的理解应该是自信的,但是,我在学习过程中,看到网上一些博文,发现即便是参加工作的一些专业编程人员,突然碰到二维数组和指针的问题时,也可能会遇到难以处理的诡异问题,并且问题一出现,很难一时间解决。

我自学已经1个多月了,对C语言了解还很浅薄。学到数组和指针的时候,我看了大量的博文和书籍并亲自动手实践,做了一些总结,希望和大家分享交流,若有错误和不足之处,希望大家好不客气的提出,以免误导他人。

好了,现在开始。

我对二维数组和指针的处理划分为两类:降维法,线性连续法。(这仅仅是我自己命命名而已)。

1) 降维法     。

我记得在一本日本作家的书里看到过这样一个理念:C语言其实没有所谓的“二维(多维)数组”。此说法的 依据是:拿二维数组来说,其实就是一个特殊的一维数组,特殊在于它里面的元素又是若干个数组。若把里面的数组看做是一个元素,那么,这个数组就是普通的一维数组了。降维法的思想就是如此。

如何降维?

例如:int arr[3][2]={{1,2},{3,4},{5,6}};  我们去掉arr[3],就剩下int [2],那么int[2]就是降维后的“一维数组”的                  元素的类型,也就是说:{1,2}  和 {3,4}和{5,6} 这3个元素的类型是int[2]型。现在,你就把这个数组当做是一                维数组看待吧。同样,我们定义一个指针去指向这个数组,当然这个指针的类型必须要和这个“一维数组”的                类型一致,所以,定义为:int (*p)[2]   (请注意这个与int*p[2]的区别) 。接下来就是让指针变量p指向数组                      了,和一维数组一模一样,  p=arr   或者 p=&arr[0]。下面我们来多数组进行处理。

# include <stdio.h>

int main (void)

{

int arr[3][2]={{1,2},{3,4},{5,6}};

int i,j;

int (*p)[2]=arr;     //或者= &arr[0]

for(i=0;i<3;i++)

for(j=0;j<2;j++)

printf("%d\n", *(arr[i]+j) ) //或者 *(*(arr+i)+j ) ,因为arr[i]等价于*(arr+i)

return 0;

}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

函数形式:

# include <stdio.h>

void test(  int (*a)[2] , int row )

{

int i,j;

for(i=0;i<row;i++)

for(j=0;j<2;j++)

printf("%d\n",*(*(a+i)+j) );

}

int main (void)

{

int arr[3][2]={{1,2},{3,4},{5,6}};

int (*p)[2]=arr ;   //或者= &arr[0]

test(p,3);           //其实也可以不用定义P指针,直接发送arr或者&arr[0]也可以

return 0;

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

函数形式:情景:找出一个二维数组每行的最大值,并输出。

# include <stdio.h>
           void test(int (*a)[2],int row) //形参是“一维数组的地址”和 行数。 
          {
                 int max;

for(int i=0;i<row;i++)   //用i控制行 
                 {
                     max=a[i][0];           //假定每行第一个元素最大 
      
                     for(int j=1;j<2;j++)   //每行第以最大,那么就从每行第2个数开始就可以了,即j=1; 
       
           
                     if(  *(*(a+i)+j)>max   )          或者  //if(*(a[i]+j)>max)
                          max= *(*(a+i)+j);             或者  // max=*(a[i]+j);
                     printf("%d\n",max);                //输出最大值 
                }

}

int main(void)
       {
                int arr[5][2]={{5,2},{31,4},{5,63},{34,555},{131,1}};

int (*p)[2]=arr    //或者=&arr[0]
   
                test(p,5); 
                return 0;
      }

线性连续法:

我们要知道:二维(多维)数组的最基本元素在内存中的储存方式是线性连续的,而不是平面的。

如上图:定义一个二维数组:int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}},假定2000是元素1的地址,我               们发现这个数组的最基本元素的地址是连续的,于是我们就可以用这个属性来处理二维数组。

比如我们在对一个二维数组通过scanf函数初始化的时候(或者全部输出),这时不会考虑二维数组形式上的               问题(如他是几行,几列),我们只是把他们一个一个赋值而已,可以这样。

# include <stdio.h>

int main (void)

{

int arr[3][4];

int *p=&arr[0][0];

int  i , len=3*4;//总最基本元素个数

for(i=0;i<len;i++)

scanf("%d",p++); //有人会怀疑p++是否正确,那请你去弄清a=i++ 和a= ++ i的区别。

p=&arr[0][0];         //请特别注意这条语句的作用。想想他是干什么用的。没有他会怎么样。

for(i=0;i<len;i++)    //p每增加1,就变成了下一个最基本元素的地址,由1的地址变为3的,5的,7的,9的,11                                                       //的...

printf("%d\n",*p++);

return 0;

}

有人会说:这种方法不方便对二维数组以矩阵的形式处理,请看接着看。

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

函数形式:情景:找出一个二维数组每行的最大值,并输出。

# include <stdio.h>
            void test(int*a,int row,int col)    //定义函数,形参为:整形指针,行数,列数。
         {
            int  i, j, max;
            for(i=0;i<row;i++)               //用i控制行
          {
             max=*(a+i*col+0);           //假定每行第一个元素最大
 
             for(j=1;j<col;j++)            //通过循环对每行的元素间进行比较,确定最大值。注意;这里j从1开始,而不是0
             if( *(a+i*col+j)>max )     //当然也可以从0开始,不过那样就重复比较了。
                 max=*(a+i*col+j);

printf("%d\n",max);         输出每行的最大值。
 
            }

}

int main(void)
      {
          int arr[3][2]={{351,12},{1,45},{78,110}};
           int *p=&arr[0][0];                 //取第一个最基本元素的地址
          test(p,3,2);                          //发送地址,行数 列数

return 0;
      }

我们会发现,线性连续法在取数组地址的时候很简单粗暴,就是取数组的第一个最基本元素就OK了,如果想要重     新利用二维数组的矩阵形式,这里用了一个小技巧,请看: *(a+i*col+j)它表示每个最基本元素 
,简单起见,我         们把col换成眼前问题的列数2,也即是*(a+i*2+j),首先明确:括号里面的是每个基本元素的地址,a是起始地址,       是一个导火索,i*2 是用来让地址“换行”的,j则是让地址在i确定(即一个行)的情况下遍历这行的每个元素的地         址。请牢记:i*col, 这里的col是列数。

写在最后:第一次写博客。所以,存在错误也请大家谅解。希望大家踊跃提出意见。谢谢。

date  :2015-02-12 21:58

关于c语言二维数组与指针的个人理解及处理办法。的更多相关文章

  1. C语言 二维数组(指针)动态分配和释放(转)

    C 二维数组(指针)动态分配和释放 先明确下概念: 所谓32位处理器就是一次只能处理32位,也就是4个字节的数据,而64位处理器一次就能处理64位,即8个字节的数据.如果我们将总长128位的指令分别按 ...

  2. c语言二维数组与指针

    问题,以下输出的结果是什么,区别在于哪? void main() { ][] = { ,,,,,,,,,,, }; //输出的3个地址都一样,差别在哪? printf("\n%x" ...

  3. 二维数组和指针(C语言)

    二维数组和指针 二维数组和指针1.二维数组和数组元素的地址若有以下定义:int *p, a[3][4]; 1)二维数组a由若干个一维数组组成在C语言中定义的二维数组实际上是一个一维数组,这个一维数组的 ...

  4. 程序员之--C语言细节13(二维数组和指针,&amp;*a[i][0]的理解,数组1[e]和e[1]非常可能你没见过)

    主要内容:二维数组和指针.&*a[i][0]的理解.数组1[e]和e[1] #include <stdio.h> #define NUM_ROWS 10 #define NUM_C ...

  5. C语言教学--二维数组和指针的理解

    对于初学者对二维数组和指针的理解很模糊, 或者感觉很难理解, 其实我们和生活联系起来, 这一切都会变得清晰透彻. 我们用理解一维数组的思想来理解二维数组, 对于一维数组,每个箱子里存放的是具体的苹果, ...

  6. c语言编程-----指向二维数组的指针

    c中如何返回一个指向二维数组的指针 #include <stdio.h> #include <stdlib.h> #define COUNT 3 typedef int (*M ...

  7. 对二维数组使用指针进行操作的探索(C语言)

    /* Name: 对二维数组使用指针进行操作的探索 Copyright: Author: lingr7 Date: 01/12/18 11:55 Description: */ #include< ...

  8. c语言二维数组传递

    c语言二维数组传递,目前我总结三种方法,以及纠正一个不能使用的方法 /********************************* * 方法1: 第一维的长度可以不指定 * * 但必须指定第二维 ...

  9. C语言多维数组的指针传递

    在C语言中为了节省空间,提高运行速度经常使用指针来完成数组的传递. 对于一维数组而言可以直接传递首地址 而对于二维数组必须在传递时声明是二维数组的指针,并且调用时也要经过一些运算 首先是定义形参: 函 ...

随机推荐

  1. logback 配置详解【讲解较全的博客网站】

    http://blog.csdn.net/haidage/article/category/812478 详解(一)http://blog.csdn.net/haidage/article/detai ...

  2. 最大子矩阵和 URAL 1146 Maximum Sum

    题目传送门 /* 最大子矩阵和:把二维降到一维,即把列压缩:然后看是否满足最大连续子序列: 好像之前做过,没印象了,看来做过的题目要经常看看:) */ #include <cstdio> ...

  3. 线段树 Codeforces Round #197 (Div. 2) D. Xenia and Bit Operations

    题目传送门 /* 线段树的单点更新:有一个交叉更新,若rank=1,or:rank=0,xor 详细解释:http://www.xuebuyuan.com/1154895.html */ #inclu ...

  4. bzoj1028 [JSOI2007]麻将

    1028: [JSOI2007]麻将 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1337  Solved: 601[Submit][Status][ ...

  5. 骨牌铺方格[HDU2046]

    骨牌铺方格 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  6. CentOS6.4 配置LVS(DR模式)

    DR模式中LVS主机与实际服务器都有一块网卡连在同一物理网段上. IP分配 VIP:10.10.3.170 RIP1:10.10.3.140 RIP2:10.10.3.141 1.安装所需的依赖包 y ...

  7. [Unity2D]预制件Prefab

    预制件Prefab是一个组件模板,比如在游戏里面要实现开枪的时候会有子弹不停地从枪口飞出来,那么就可以通过Prefab来实现子弹的游戏对象,表示所有的子弹都是从同一个Prefab来构建出来的,也可以理 ...

  8. 51NOD 算法马拉松12

    OTZ做出题目的神犇..断断续续改完了在这里存一下思路吧 A题:第K大区间题意:定义一个区间的值为其众数出现的次数.现给出n个数,求将所有区间的值排序后,第K大的值为多少. 分析:二分答案mid,任务 ...

  9. wc2016总结

    因为我太弱了,高一才第一次来wc. 前几天讲课,被各种小学微积分和初中高等代数虐,简直naive.只好自己做做bzoj,想着练练模板之类的东西. 考试当天自觉状态不错,翻开试题感觉各种神奇(这难道是串 ...

  10. hiho#1033 : 交错和

    描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义交错和函数: f(x) = a0 - a1 + a2 - ... + ( - 1)n - 1a ...