代码之家  ›  专栏  ›  技术社区  ›  JoeSlav

通过参考3维定长数组

  •  2
  • JoeSlav  · 技术社区  · 14 年前

    任何人都能提示如何通过引用传递此类数组吗

    int array[2][3][4];
    

    所以我可以保存他的指针以便使用和修改数组? 比如,如果我说的是一个整数:

    // Scope 1
    int a = 3;
    increment(&a);
    // End Scope 1
    
    // Scope 2
    int *pa;
    void increment(int *tpa) { 
      pa = tpa; *pa++; 
    }
    // End Scope 2
    

    非常感谢,谨致问候。

    4 回复  |  直到 14 年前
        1
  •  8
  •   James McNellis    14 年前

    如果您真的想通过引用传递数组,可以这样做:

    void f(int (&a)[2][3][4]) { }
    

    在C中,它不具有引用,可以通过指针传递数组(当然,这也在C++中工作):

    void f(int (*a)[2][3][4]) { }
    
        2
  •  3
  •   Armen Tsirunyan    14 年前

    C++:

    void f(int (&array)[2][3][4])
    {
    }
    

    C:C中没有引用

    请注意,无论如何传递数组,无论是否通过引用,都不会复制数组,因此您将得到原始指针。您也可以像这样传递这个数组:

    void f(int array[][3][4])
    {
    }
    
        3
  •  2
  •   JoeSlav    14 年前

    感谢所有参与此活动的人!sskuce利用“容器”提供了一个非常好的解决方案。我考虑过这个,但不太喜欢额外的东西。 我在一点点混乱之后才意识到詹姆斯·麦克内利斯一直都给出了答案。所以…以下是我喜欢的解决方案,没有容器,也没有索引算术(注意括号):

    void Scope1() 
    {
        int array[2][3][4];
        Scope2(&array);
    }
    
    int (*pArray)[2][3][4];
    
    void Scope2(int (*tpArray)[2][3][4])) 
    {
        pArray = tpArray;
        (*pArray)[0][0][0] = 3;
    }
    

    再次感谢大家。

        4
  •  1
  •   Sam Skuce    14 年前

    编辑:我将原始答案保留在下面,因为我认为人们有必要了解数组实际上是如何传递给函数的,以及它们是如何在内存中布局的,但是经过进一步的思考,我认为有一种简单而正确的方法来完成您想要的工作。

    将数组封装在结构中,例如

    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.
    }
    

    这个结构允许您维护封装数组的布局信息,并且不必担心讨厌的索引算法。

    -----旧答案----- 传递对数组的引用是没有用的,除非您想更改数组的大小或布局(无论如何,静态大小的数组都不能这样做)。即使通过“value”传递数组,也将获得对数组元素的引用(或指针)。也就是说,如果您声明您的函数:

    void f ( int a[2][3][4] ){
        a[0][1][2] = 42;
    }
    

    像这样称呼它 f( array ) 什么时候 f 出口, 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;
    

    基本上,将每个索引乘以可以被该顺序的索引引用的元素数,例如 k 在给定一个固定的 j n 索引,每个 J 索引可以指向4个元素,给定一个固定的 n 索引,以及每个 n 索引可以指向12个元素中的一个(因为12=3*4)。

    就像我说的,这很棘手。查看维基百科上的文章 Array Data Structures Row-major order 以便更好地了解这些东西的布局。