c语言中二维数组的问题

来源:互联网 发布:mac升级系统 编辑:程序博客网 时间:2024/05/20 06:23

在论坛上看到一个关于二维数组讨论的帖子,觉得很有价值就整理了一下转帖了过来

1)二维数组  参数传递 和二维数组的定义是一个道理。

 

        二维数组声明时要求给定第二维下标。(同样,多维数组声明时要求给定除第一维外其他所有维的下标)

 

这是因为不管几维数组在内存中的存储和一维数组没有本质区别,都是线性存储的,长度是各个维下标之积。

 

程序运行时访问二维数组的某元素时要靠各维下标作偏移指标,比如a[10][3],只有给定第二维下标“3”,

当你写a[10]时,程序才知道要从a这个位置向后移动10个“3”。

 

参数的道理相同,也是局部变量的一种,和你在函数中声明的变量没有太大区别(栈中的位置不同)。

所以必须这样写:void trans(int a[][3], int b[]);

 

#include <stdio.h>

#include <stdlib.h>

 

void trans(int a[][3], int b[]);

 

int main(void)

{

    int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };

    int b[9];

    int i;

 

    trans(a, b);

 

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

        printf("%d/t", b[i]);

    printf("/n");

 

    exit(0);

}

 

void trans (int a[][3], int b[]) {      //形参

    int i, j, k;

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

        for (j = 0; j < 3; j++) {

            b[k++] = a[i][j];

        }

    }

}

二维数组做参数

#include <iostream>

using namespace std;

void pb(char** a)

{

 cout<<a[1][1];//只是测试调用成功不

}

int main()

{

      char a[2][2];

 

      for(int k=0;k<2;k++) {

 

            for(int w=0;w<2;w++)

                    cin>>a[k][w];

       }

       pb((char **)a);

//二维数组做参数强制转换也有错!

       return 0;

}

有什么好办法传递参数,吗,最好能有完整程序!谢谢

 

提问者: yjc_5252 - 试用期 一级 最佳答案

#include <iostream>

using namespace std;

void pb(char a[][2])

//一楼的稍改下,100改为2,即 a[][2]

{

 cout<<a[1][1];

}

 

int main()

{

      char a[2][2];

 

      for(int k=0;k<2;k++){

 

                 for(int w=0;w<2;w++)

                         cin>>a[k][w];

        }

 pb(a);

 return 0;

}

 

参考资料:一楼

 0回答者: 江玉菡 - 试用期 一级   2009-5-25 20:56

 

其他回答    共 1 条

#include <iostream>

using namespace std;

void pb(char a[][100])

{

       cout<<a[1][1];

}

int main()

{

        char a[2][2];

 

        for(int k=0;k<2;k++)

                for(int w=0;w<2;w++)

                        cin>>a[k][w];

        pb(a);

return 0;

}

 

搞人的二维数组指针,求助!

事情是这样的,我们老师说对于声明如下的  

   

  int   a[4][5];  

   

  a这个二维数组,它的类型实际上是int**,  

  但是我在编程的时候试,写了下面的代码:  

   

  int   a[4][5];  

  int**   p   =   a;  

   

  VC中说不能将int   [4][5]转化成int**,  

  BCB和Dev-C++中说

不能将int   (*)[5]转化成int**,  

   

  所以我想应该是老师弄错了,

 

实际上一个二维数组的类型是int   (*)[n](其中n是第二维的维数)  

  用  

   

  int   (*p)[5]   =   a;  

   

  就行了。  

   

  我跟我们老师说,她坚持说int**是对的。  

  大家怎么看啊?我都有点晕了。

 

 

2 楼goodboy1881

 

 如果要如此写,你写  

  int**   p   =(int**)a;  

  尝试一下。  

  要不然你说这个a怎么解释,是二维数组第一行的首指针?还是二维数组的首指针?

 

3 楼

 她说二维数组是int**型的,但是赋值指针的时候和类型又是不一样的,两者是有区别的。  

  所以我感到很奇怪,为什么赋值的时候不一样的,还要说二位数组是int**,  

  要不然为什么不能用一个int**的指针指向它呢?这不是明显的赋值不相容吗?

 

5 楼SaiRose(Learning......)

 

指针!=数组名  

    int   a[4][5]它的类型绝对不是int**  

   只是函数在传参数的时候会将数组转化为指针  

   具体的查书了,c专家编程上有详细讲解

 

6 楼qingyuan18(zealot_tang)

 二维数组名不能简单理解成二维的指针,

int   a[4][5];

a是二维数组的首地址,但它不是一个int   **型的指针。  

 int**   p   =   a;

这样赋值是错误的,用指针对二维数组的操作应该参考用指针数组(int   *   p[4])

 

或者或者行指针((int   *)p[4])的方式

 

7 楼anyy0929()

 

 同意上面的,a是二维数组的首地址,

 

而P是指向指针的指针,不能这样赋值~~~

 

8 楼ywhs()

 

 我想问的是int   a[5][3]中a的类型是int**吗?

 

 

 

12 楼FreeFice(庄鱼)

 

int   **用于表示二维数组的缺点在于指针的间隔无法确定,因此,虽然,int**可以描述二维数组,但地址并不是“自动”的一次性赋给的,作为定长多维数组,在很多时候可以被当作一位数组直接操作,然而,多级指针却绝不可以这样,这是数组与指针最本质的区别。如果一定要问int**与什么数组形式相对的话,int**   =   int[][],

 

而int[][]与int[5][3]完全是两回事。

 

13 楼

 

  多维数组在意义上和指针完全不是一回事了  

  指针是一个间接指向的过程   

   

  但是多维数组,确实一个定点计算的问题  

   

  作为参数传递的时候,也不能如此直接传递  

  必须强制转化为一维数组,然后给出各个原始纬度的大小,再通过计算偏移得到原始数据

 

14 楼

给个例子  

   

  int   a[2][3];  

  int**   p;  

  p   =   new   int*[2];  

  p[0]   =   new   int[3];  

  p[1]   =   new   int[3];  

   

  然后你反汇编这段代码:  

   

  a[1][2]   =   5;  

  p[1][2]   =   5;  

    

  汇编代码都不一样...

 

  a[1][2]   =   5;

00416AFE     mov        dword  ptr [ebp-8],      5    

  p[1][2]   =   5;   

00416B05     mov       eax,        dword ptr [p]    

00416B08     mov       ecx,     dword  ptr   [eax+4]    

00416B0B     mov      dword  ptr  [ecx+8],         5    

   

  这个是我针对我的例子反汇编的结果,认为可以相互转换的朋友,可以看看 

15 楼

 

 这么用  

  int   a[4][5];  

  int**   p   =   &a[0];  

  其实区别就在二维数组的空间为连续,而二维指针申请的堆空间不是。  

 

 

 18 楼

 

二维数组名不能简单理解成二维的指针,int   a[4][5];

a是二维数组的首地址,也是数组第一行的首地址(在数值上是一样的),但它不完全等同于一个int   **型的指针。  

   

  int**   p   =   a;这样赋值是可以的,多维数组就只能用多层的指针,(使用数组名除外)。至少这点在TC中是完全正确的,也许VC有不同的规定!!

 

19 楼

可以用,不代表会正确,下面这个代码在C中都没有问题:  

   

  char   c;  

  int*   p;  

  c   =   'a'  

  p   =   &c;  

  *p   =   65535;  

   

  赋值确实可以,但是执行结果不会正确...

 

20 楼   

      int[][]是什么意思?

           为什么int**   ==   int[][]?  

      int[][]与int[5][4]分别表达什么?有什么区别?

21 楼

 

  其实,int   a[4][5];

 

  这种型式中,a的类型为:int   (*   )[5];  

  是的,编译器会把最后一维的数量做为类型的一种参考,更严格一点说的话,应该是:int   (*   const   )[5];  

 

22 楼

int   a[4][5];

这种型式的的确确会在“很多时候可以被当作一位数组直接操作”。但最好不要这样做,我觉得不安全。

 

23 楼

  int   [][]二维不定数组,

C/C++中并不允许这样描述,根据C/C++对数组的定义要求:在做参数声明时,仅允许存在一个[](第一个)以表示数组大小的不确定性。数组大小在非参数声明时必须明确指明或初始化的。上面用int   [][]   <=>   int   **主要目的在于表述没有一种数组形式可以与int**相对应。指针*与数组[]实际上是不能用等号相联系的,唯一的例外是字符串char*char[]一致,但实际上,字符串并不是什么指针,而是类似于隐式链表的数组(必须满足空字节结束表示),用于写成指针格式纯属早期编程习惯。千万不能拿来当验证指针与数组关系的工具。  

  由于指针的外延比数组(包括不定数组)大得多,因此,通常可以将A[4][5]赋值给B[][5]赋值给*C[5],但反过来却是不行的。

 

 

 

关于二维数组指针的问题

 

这是主函数

main()

{

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

     printf("  %u/n  %u/n  %u/n  %u/n  %u/n  %u/n",

     a+1,a[1],&a[1][0],*(a+1),*((a+1)+2),*(*(a+1)+2));

}

输出的结果是

65480

65480

65480

65480

65496

6

我想问一下从前三个可以看出a+1==*(a+1)可是为什么

*((a+1)+2)和*(*(a+1)+2)的结果不一样谁能能解释一下吗

 

其实这是C在实现多维数组时的魔术而已,实际上a就是一个12个int的数据区。你在写a[1][2]时编译器实际上知道这个数组一行是4个元素,所以计算它的地址为a+(1*4)+2,即a[1][2]就是*(a+(1*4)+2)。

 

另一方面,编译器允许使用形如a[1]这样的表述,由于它知道a是一个定义为a[3][4]的数组,所以它知道a+1实际上应该a这个首地址加上4int的大小,你如果再试一下就会发现在int为4个字节的机器上a[1]应该是a加上4.

 

C语言中的指针的值虽然可能是同一个内存地址,但是编译器知道它的语言不同,在做同样的指针增量的时候加的地址也是不同的。就像你如果把a的值强制转换成char *,比如char *p = (char *)a;再看p+1就只是指向a[0][0]的第二个字节了一样。同样的+1,含义却是不同的。

 

这样你就应该明白了,虽然*(a+1)的值只能是跟a+1一样,因为它也只能指向a[1][0],但是编译器知道它再增量的话就只需要加上1int的大小,而不是4int的大小了。因此*((a+1)+2)实际上是指向a[3],而*(*(a+1)+2)就是*(a[1]+2),也就是a[1][2]了。

#include<stdio.h>

 

void f(int a[][3])

{

     a[1][1]=32;

     a[1][2]=348;

}

 

int main()

{

    int a[3][3];

    f(a);

    int *b;

    b=(int *)a;

    printf("%d",*(*(a+1)+2));

    printf("%d",*(b+5));

    scanf("%d");

    return 0;

}

a+1代表第二行的首地址,(性质仍为二重数组)因此,a[1][2]可以用*(*(a+1)+2)来访问。

二重数组也可以用一维指针来访问,因为二维数组在内从中是按照从左到右从上到下的顺序排列的。b+5是第五个数的地址,按照二维数组在内存中排列的方法也就是a[1][1].

 

二维数组还可以用二维指针来访问:

#include<stdio.h>

 

void f(int a[][3])

{

     a[1][1]=32;

     a[1][2]=348;

}

 

int main()

{

    int a[3][3];

    f(a);

    int (*p)[3];

    p=a;

    printf("%d",p[1][1]);

    scanf("%d");

    return 0;

}

上面的p表示指向二维数组的指针,该数组每行共计四个元素。

注意与char *a[4]相区别。后者是一个指针数组,每一个数组元素指向char型元素。

原创粉丝点击