编辑:我在下面保留我的原始答案,因为我相信人们有必要了解数组实际上是如何传递给函数的以及它们是如何在内存中布局的,但经过进一步思考,我认为有一个简单的和正确的方法来完成你想做的事情。
将数组封装在结构中,例如
typedef struct ArrayHolderStruct{
int array[2][3][4];
} ArrayHolder
//...
//scope 1
ArrayHolder thingy;
thingy.array[0] = something;
//other initialization.
F( &thingy );
//...
//scope 2
ArrayHolder *pa;
void F ( ArrayHolder *p ){
pa = p;
p->array[0][1][2] = 42;
}
//Call F first to set pa.
void G(){
pa->array[0][1][2] = 6 * 9; // if pa = &thingy, thingy will be modified.
}
该结构将允许您维护有关封装数组的布局信息,并且您不必担心讨厌的索引算法。
-----旧答案-----
传递对数组的引用是没有用的,除非您想更改数组的大小或布局(无论如何您都不能使用静态大小的数组)。即使您通过“值”传递数组,您也会获得对数组元素的引用(或指针)。也就是说,如果你声明你的函数:
void f ( int a[2][3][4] ){
a[0][1][2] = 42;
}
当f 退出时,像f( array ) 一样调用它,array[0][2][2] 将被设置为 42,即使您没有将“引用”到 array 传递到函数中。
如果您想保存指向数组的指针以供以后在库函数等中使用,您可以执行以下操作:
//scope 2
int * pa;
void f ( int a[2][3][4] ){
pa = &a[0][0][0];
}
在这一点上变得很棘手 - 你必须知道 pa 在内存中是如何放置(放置?)的。我认为 C 已经对“行主要顺序”进行了标准化,所以数组应该像这样在内存中布局:
a[0][0][0] a[0][0][1] a[0][0][2] a[0][0][3] a[0][1][0] ... a[0][2][3] a[1][0][0] a[1][0][1]... a[1][2][3]
因此,要获取索引 [n][j][k] 处的元素,您必须执行以下操作:
pa[n * 12 + j * 4 + k] = something;
基本上,将每个索引乘以该顺序索引可以引用的元素数,例如给定固定的j 和n 索引,每个k 索引恰好指向一个元素,给定一个固定的n 索引,每个j 索引可以指向4 个元素,每个n 索引可以指向一个12 个(因为 12 = 3 * 4)个元素。
就像我说的,这很棘手。请参阅 Array Data Structures 和 Row-major order 上的维基百科文章,以更好地了解这些内容的布局。