西西河

主题:【求助】向各位高手请教一个c语言中数组与指针的问题 -- 数值分析

共:💬84 🌺26 新:
全看树展主题 · 分页首页 上页
/ 6
下页 末页
家园 似乎是概念错误

无论是多少维德的数组,其数组名都是指针,而不是指针的指针。

比如说你的a,尽管是二位数组,其数组名其实只是指向数组首地址的指针。具体这个数组多少维,每一维的长度是多少,那是另外的信息。

所以如果编译器允许,你的函数应该写为

void f1(int a[][5]),表明这是一个两维,最低维长度为5的数组。可以直接引用。

如果编译器不支持,可以写为

void f1(int* a)

然而你必须知道这是个几维的数组,每维的长度是多少。

而引用a[i][j]的时候就写为

a[i*5+j]

如果都不知道,就写为

void f1(int* a, int dimension, int* dimensionLength)

——————————————————————

int** a是指向指针的指针。通常用于指针数组(比如说链表之类),不可以用于多维数组

dimension 表明这个数组是几维的,

dimensionLength表明每一维的长度。

家园 del
del
家园 您说的是“多维数组名”这类的“指针常量”吧

比如int a[3][4],这里的a其实是一个指向数组的指针。如果要和变量对应的话a应该是和

int (*pa)[4];

里的pa相同类型的一个常量。

家园 我理解int a[3][4]的a的类型不是int *

也不是int **

应该是int (*pa)[4]中的pa这种类型。

也就是说a和pa都是一个指向含有4个元素的int数组的指针。只不过a是常量。

pa++的话指针应该向下移动4*4byte。

当然,此时a里存的地址和a[0][0]元素的地址是相同的。只不过a+1不是a[0][1]的地址,而是和a[1][0]的地址相同。还是指针的“基类型”的问题。

del
家园 可以试试强制类型转换

比如

int *p = (int*)a;

应该是可以的。

指针说白了就是一个里面放着地址的变量。啥地址不是地址啊

此时a应该是一个“指向数组的指针”类型的常量。

家园 “指针数组”vs“数组指针”

int *pa[4]

vs

int (*pa)[4]

我觉得楼主的困惑可能是这两个的区别。

家园 del
del
家园 指针里面放的就是地址

只不过它知道(或者说它认为自己知道)自己要指向的是个什么类型的玩意儿。(其实确切的说是编译器认为)

还是先确定下角色吧,这样好说。

路人甲:int a[3][4];

路人乙:int *p;

a知道每行的宽度,是因为您交待它了,它的“基类型”是一个有4个元素的int数组。也就是说这时它就认为自己指的东西有4*4byte那么长。所以您让他+1,他自己就找下一个了。也就是给自己所存的数(就是地址)加上了个16。所以您看到a+1就是a[1]也就是数组第二行的地址。

但是

p=(int *)a

的时候,您交待a了,这会儿你不能跟p说你是个数组指针,要这么说它就不跟你玩儿了。你就跟他说你是个int指针。反正都是地址,那家伙瞧不出来

于是,p就从了……

家园 说得不错...
家园 用法不同吧

我以前做得项目用的基本都是C。已经有两年多没有碰这种指针运用了。

如果我记得没错,以int* 方式传过去的,都可以向我说的那样用。a+1这种我还没有正经用过。

家园 你这个我都看糊涂了

肯定不对,但不知道你迷糊在什么地方。C原则上没有多维数组的概念,任何多维数组实际上都是一个更长的一维数组。你这个地址传递当然是对的,C只管把地址传过去不管你传的是什么地址,自己保证正确。问题在于即使主函数里面定义了个a[m][n],函数f1里面并不知道n,你也无法重新定义,a[0][0]也许还能知道(没把握),其他的统统不知道是何物。

C原则上是不推荐多维数组的,部分原因就在于会引起你这样的混乱。替代方法简单,开始就定义为一维数组a[m*n],使用的时候也按照这个方法使用即可。至于带两个星号的比如int **x,这个是多级间指,**x才是int数字,而多维数组的a,不管多少维,即使是int a[i][j][k][l][m][n],*a就是数字。二者完全不一样。(int **)a等于是进行了强制类型转换,把一个int指针变成了一个指向指针的指针。

根本上,我还是建议你在C不要用多维数组,一干二净。

家园 你搞错了多维数组的概念。

在c里,默认多维数组结构,实际上一通过一个内存片实现的。a[][],指向一个内存片,a指向首地址,从首地址开始,里面顺序存着a[0][0],a[0][1].....a[1][0]a[1][1]...等等。。

int**类型指向一个地址类型,which指向一个int。

所以a[][]定义里a是个指向int的指针,而不是指向一个int指针的指针。

----------------------------------

另外一种常用的动态实现多维数组的方法是这样子的。

假如要实现一个5*5的二维数组,

int ** a = (int **) malloc(5*sizeof(int *));

for (int i = 0;i<5;i++) {

a[i] = (int *) malloc (5*sizeof(int));

}

之后就可以用a[1][2]的形式访问多维数组,传递的时候传递int**类型。但要注意越界和释放问题。

家园 呵呵,没错。我们一般也就和老兄说的那样,用个int *

a+1这种用法只是在讨论理论的时候提提,一般不会用。太乱。

家园 我对指针的理解是这样的

其实指针这东西,只需要搞清两件事情:

1.指针就是个很普通的变量,只不过它里面放的不是具体的数据,而是一个地址。您要是*它,它就按着自己记下的地址去提货。

2.指针知道自己的“基类型”是个什么类型。它永远认为自己记的那个地址里放的就是基类型的数据。这点很重要,因为:

2.1 其实指针里放的只是一个起始地址,您*它的时候,它就按照自己的“基类型”的长度从它记的地址开始去取那么长的内存数据。并且将这些二进制按“基类型”的方式解读:这么多位0和1到底记录的是一个整数,还是一个数组,还是一个浮点数。

2.2 您要给指针+n,它就认为是要它指向后面第n个“基类型”数据。所以它会把自己记的地址加上个

n*基类型长度

这个第一点,只要是使用指针的都知道,没啥可说的。所以我们要用一个指针的时候,需要注意的就是要时刻记得这个指针的“基类型”是什么,这个影响到指针的大部分行为特点。

数组和指针,就一句话。数组名是一个“基类型”是数组元素类型的指针常量。可以向指针一样用,但不能改变其取值。

多维数组也是一句话。多维数组是“数组的数组”。

其实我认为C语言里的指针和数组就这么点儿东西。

希望对您有帮助。理解不对的地方也请大牛们指正。

家园 不错,这样在使用的时候更方便点儿了。花

请教老兄一下,这样弄出来的“二维数组”不是在栈里而是在堆里吧?

内存里这些int也是5个一伙5个一伙散布的,不一定是25个挤在一起的吧?

全看树展主题 · 分页首页 上页
/ 6
下页 末页


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河