西西河

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

共:💬84 🌺26 新:
全看树展主题 · 分页
/ 6
下页 末页
家园 【求助】向各位高手请教一个c语言中数组与指针的问题

最近遇到一个c语言中数组与指针的问题,看到版中高手云集,望各位能不吝指教一二。

是这样的,以前学过c语言,好久不用了,最近作一个小程序。我一直认为二维数组和二阶指针是一回事儿(看来是基础没打牢啊,惭愧,惭愧。)但最近才发现问题。

举个例子来说吧,假如我定义一个函数f1

void f1(int **x)

{

......

}

再在main函数中定义一个int型二维数组

int a[5][5];

然后用循环对a赋初值

然后把它传到函数f1中,

f1((int **)a);

问题来了,在f1中无法正确访问数组。

可是我把地址值打印出来,main函数中a的值与f1中x的值是一样的,(比如都是0x12345678) 但f1中x[0][0]与main中a[0][0]却不一样。

为什么对同一个地址解引用,结果会不同呢?

求教诸位,

先行谢过。

家园 try to answer

f1中的a 是指针的指针类型,和main中的a (数组指针类型)类型不一样。

当f1函数调用的时候,main中a的类型被强制转换了。

所以f1中的a 不能按照数组的方式使用。

家园 我是这么理解的

如a[4][3],二维数组名下有四个子地址,这每一个子地址都可以看作一维指针来处理,

但这个二维数组的首地址就是其第一个子地址的地址,若把它看作二维指针的话,那就容易导致错误.

如二维指针**P, *p,是一个地址,这个地址指向一组数据,这一组数据仍是地址,但其第一个子地址的值却可以是变化的,这与数组不同, 我猜想编译器,就禁止了用二维指针来操作二维数组.

家园 把f1定义成

void f1( int x[5][5])

再试试

家园 这样那当然是没有问题了

这样那当然是没有问题了。

实际上因为子函数不知道主函数传进来的二维数组的大小,所以才用这个方法的。

家园 供你参考:

//Note: p is declared as int*, not int**!!!

void foo(int* p, int m, int n)

{

int x ;

int i , j;

//to access p[i][j] ( 0 =< i < m, 0=<j<n):

*(p + n * i + j ) = x;

...

}

int main(...)

{

int a[5][6];

foo((int*)a, 5, 6);

int b[10][11];

foo((int*)b, 10, 11);

...

}

家园 原因是这样的(详见内)

C语言对于指针变量以下标操作取值实质上是这样做的。如果有,

int *x;

则x[m] 实际上是取地址(x+m*int长度)处的整数值

而对于int **y

则y[m][n] 实际上是取地址 (y+m*(int*长度))中的值后,再加上n*int长度的值,以新值做为一个地址再取该地址中的值。

而对于二维数组int a[h][c],

a[m][n]是取地址 a+m*c*int长度 + n*int长度处的整数值。

也就是说,你例中的x[0][0]实质上为

*(*(x))所以其值与你预期的不一致。

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

附注:第一次a[m][n]的计算公式写错。现予更正

另外frnkl朋友指出y[m][n]计算公式中的错误,也已改正。谢谢frnkl。


本帖一共被 2 帖 引用 (帖内工具实现)
家园 考虑另一个方法呢

定义子函数为

void f1(int *x[])

{

......

}

家园 数组只能认为是指针,不能认为是递指针;

递归指针的意思,指针指向的地址保存着另一个指针。而在任意多维数组中,以数组名作为指针找到的是第一个元素的值。最佳的解决办法只能把第一维的尺寸用参数传递进去。

家园 二维数组和二维指针是两码事

二维或多维数组本质上仍是一维数组,a[5][5]等于一个长25的一维整数组。而二维指针指向一个地址序列。把a[5][5]强制转换成int**,实际是把第一行数据强制作为指针来使用,能引起程序崩溃。

你可以试一下,把a强制转换为一维指针,然后用[i*5+j]来访问a[i][j],应当是可以的

家园 del
家园 del
家园 是这样

如果二维指针与数组等价的话,要计算x[i][j]先要算x[i]=x+i*K,其中K是最后一维的维数。但你子函数中是无法得到K的值的。这是为什么说(int **)与二维数组a不是一个类型的原因之一

----------------Update-----------------------

至于x[0][0]为什么与a[0][0]值不同,是因为x[0]的值与a[0]不同,所以x[0][0]与a[0][0]值不同。

--------------再啰嗦几句----------------------

你可以查一下,a的值与a[0]的值是相同的,但x与x[0]的值是不同的。为什么?x[0]是x的值指向的地址上的值(读多少位由int*的长度决定),而a[0]的值就是a。

------------一般情况下的讨论------------------

非吾有:原因是这样的(详见内)frnkl:理解了二维array多维array就没问题了

-----------代码例子---------------------------

frnkl:试试这段代码。这个例子也很好熊熊熊熊:更详细的例子...

家园 【讨论】笔误?

则y[m][n] 实际上是取地址 (y+m*int长度)中的值后,再加上n*int长度的值,以新值做为一个地址再取该地址中的值。

这个“(y+m*int长度)”是不是应该为“(y+m*(int*)长度)”?前一个*是乘号,后面(int*)指存放int型数据的指针。

del
家园 其实x[0][0]可以用在f1中,只是编译器对

x[0][0](定义:int** x)和a[0][0])(定义:int a[4][4])如何取值的解释是不同的。

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


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

Copyright © cchere 西西河