【问题标题】:Passing a 2-D array in pure C在纯 C 中传递二维数组
【发布时间】:2013-06-22 17:14:13
【问题描述】:

我正在尝试编写一个通用矩阵转置函数

void reverse(int** v , int vertexes )
{
    for(int i=0;i<vertexes;i++)
        for(int j=0;j<vertexes;j++) 
        {
            if(v[i][j] == 1 && v[j][i]==0){
                v[j][i] = -1;
                v[i][j] = 0;        
            }
        }

    for(int i=0;i<vertexes;i++)
        for(int j=0;j<vertexes;j++) 
        {
            if(v[i][j] == -1 )
                v[i][j] = 1;
        }
} 

主要功能是

void matrix_graph::process()
{

    int v[7][7] = {
        {0,1,0,0,0,0,0},
        {0,0,1,1,0,0,0},
        {1,0,0,0,0,0,0}, 
        {0,0,0,0,1,0,0},
        {0,0,0,0,0,1,0},
        {0,0,0,1,0,0,1},
        {0,0,0,0,0,1,0}
    };

    reverse(v,7);
}

我果然得到了一个

error C2664: 'reverse' : cannot convert parameter 1 from 'int [7][7]' to 'int **'

我们能做些什么吗?

我们能做的最好的事情是访问传递的二维数组的i、j(将v 作为一维数组传递)是

v[vertexes*i][j]

【问题讨论】:

标签: c arrays graph


【解决方案1】:

随便用

void reverse(int vertexes, int v[vertexes][vertexes])

尝试使用int ** 不会立即与内置二维数组一起使用。如果您想坚持使用int ** 接口,那么您必须按照此处所述创建一个额外的临时行索引数组

Passing two-dimensional array via pointer

或这里

conversion of 2D array to pointer-to-pointer

【讨论】:

  • 错误 1 ​​错误 C2057:该行中的预期常量表达式
  • @sethi:您使用的是旧的 C 编译器。您需要 C99 编译器才能使用此功能。如果您必须使用旧编译器,则必须遵循链接中提供的选项。如果你想使用内置数组,别无他法。
  • 我明白了..这是一个非常干净的解决方案
  • Andrey ..我认为您在第二个链接 (stackoverflow.com/questions/8203700/… ) 中的解决方案也是一个很好的解决方案...2 个好处是数组仍然很容易初始化并且解决方案是本地化的.. .
【解决方案2】:

您应该小心,因为数组数组不与双指针相同。虽然数组确实会衰减为指针,但将指向指针的指针用作数组数组意味着您实际上将其用作指针数组。

而是将参数作为指向数组的指针,例如

int (*v)[7]

【讨论】:

  • 我想写一个通用函数..用户可以传递任何具有维度的二维数组
【解决方案3】:

要摆脱错误并保持您的想法,您可以按如下方式调用您的函数:

reverse(&v[0][0],7);

并修改函数和原型:

void reverse(int* v , int vertexes ){
for (int i=0; i<vertexes; i++)
    for (int j=0; j<vertexes; j++){
    // do stuff 
    v[i*vertexes+j]; //equivalent of v[i][j]
    v[j*vertexes+i]; //equivalent of v[j][i]
}

【讨论】:

    【解决方案4】:

    我想这里一个好的设计是创建一个Matrix 类来封装矩阵上的操作。我还建议不要使用指针来存储矩阵的数据,而是使用一维数组和索引转换,例如:

    int &Matrix::at( int i, int j )
    {
        // check the constraints
        return m_array[i * m_width + j];
    }
    

    这简化了内存管理并防止在处理不必要的复杂构造时处理错误。

    C/C++ 中的多维数组不与指向指针的指针指向...指向指针的指针相同。多维数组实际上是一个连续的内存区域,由编译器完成索引转换,而指针指针是指向其他维度的指针的一维数组。在这种情况下,内存可能不是连续的,并且在这种情况下还有额外的指针,在多维数组的情况下是不存在的。

    总结一下,如果是数组:

    int array[7][7] = { ... };
    array[2][3] ===
        &array[0][0] /* start of the array */ +
        2 * 7 + 3    /* index transformation 2D to 1D*/
    

    如果是指针:

    int **pointer;
    pointer[2][3] === *(*(pointer + 2) + 3)
    

    这两个代码片段做了两个完全不同的事情,您不应该将多维数组转换为多星指针,反之亦然。

    【讨论】:

    • 对不起,一开始没有“纯C”要求,而且有一个C++标签。对于纯 C,一些围绕矩阵的包装器(struct 和支持函数)会很有用,因为传递一些随机的普通指针并不是最好的主意。数组与指针部分对于纯 C 仍然有效。
    【解决方案5】:

    我认为使用堆内存可以解决这个问题。因此,与其在堆栈中声明 int[7][7] v,不如使用 malloc 在堆中创建数组并允许您在函数之外对其进行操作。

    int** v = (int**)malloc((sizeof(int*) * 7));
    
    for (int i = 0; i < 7; i++)
    {
        v[i] = (int*)malloc(sizeof(int)*7);
    }
    // then initialize v here...
    

    【讨论】:

    • +1 我得到解决方案的唯一问题是初始化矩阵很麻烦
    猜你喜欢
    • 2011-04-20
    • 2013-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 2015-09-19
    • 2017-03-27
    相关资源
    最近更新 更多