Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 将多维数组数组的指针传递给函数,并指定边界_C_Function_Multidimensional Array_Parameters_Declaration - Fatal编程技术网

C 将多维数组数组的指针传递给函数,并指定边界

C 将多维数组数组的指针传递给函数,并指定边界,c,function,multidimensional-array,parameters,declaration,C,Function,Multidimensional Array,Parameters,Declaration,假设我有多个(数量可变)的2D数组(甚至可能是可变长度): 我现在想把它传递给一个函数。我不想将二维阵列复制到三维阵列。但是,我希望指定边界,以便函数知道2D数组的尺寸,以便使用[I][j] 我如何格式化函数的签名,使其接受指向数组(长度未知)的指针,该数组包含二维数组,它现在不接受该数组的维度 比如说 void myfunc(int[][3] *test, int len) 当然,这在语法上是无效的。在C语言中,指定数组(通过指针传递)内数组的边界是不可能的吗?我会被迫将a和b移动到指针中,

假设我有多个(数量可变)的2D数组(甚至可能是可变长度):

我现在想把它传递给一个函数。我不想将二维阵列复制到三维阵列。但是,我希望指定边界,以便函数知道2D数组的尺寸,以便使用
[I][j]

我如何格式化函数的签名,使其接受指向数组(长度未知)的指针,该数组包含二维数组,它现在不接受该数组的维度

比如说

void myfunc(int[][3] *test, int len)

当然,这在语法上是无效的。在C语言中,指定数组(通过指针传递)内数组的边界是不可能的吗?我会被迫将
a
b
移动到指针中,还是被迫将它们复制到三维数组中?

如果编译器支持可变长度数组,您可以编写

void myfunc( int rows, int cols, int a[rows][cols] );
考虑到第三个参数隐式转换为类型
int(*)[cols]
,该类型在处理一维数组指针的函数中。然而,您可以使用以下表达式

for ( int i = 0; i < rows; i++ )
{
    for ( int j = 0; j < cols; j++ ) a[i][j] = value;
}
无论如何,这是不正确的

如果要传递多个二维数组,那么可以在main中声明一个一维数组,如

int a[2][2] = {{1,2},{3,4}};
int b[2][2] = {{5,6},{7,8}};
//...

int ( *p[] )[2] = { a, b, /*...*/ };
然后将其传递给函数

在这种情况下,函数将如下所示

void myfunc( int ( **p )[2], size_t n );
这是一个演示程序

#include <stdio.h>

void myfunc( int ( **p )[2], size_t n )
{
    for ( size_t i = 0; i < n; i++ )
    {
        for ( size_t j = 0; j < 2; j++ )
        {
            for ( size_t k = 0; k < 2; k++ ) printf( "%d ", p[i][j][k] );
            putchar( '\n' );
        }
        putchar( '\n' );
    }
}

int main(void) 
{
    int a[2][2] = {{1,2},{3,4}};
    int b[2][2] = {{5,6},{7,8}};

    int ( *p[] )[2] = { a, b };

    myfunc( p, sizeof( p ) / sizeof( *p ) );

    return 0;
}
如果数组的第一个维度不是固定的,并且是变化的,那么您也可以将数组的第一个维度的数组传递给函数

  • 通过两个独立的论点;或
  • 创建某种包含(指向)所述内容的数据结构,并传递(指向)所述内容的(指针) 不管你的东西是数组还是其他东西

    当你拥有数量可变的东西时,同样的事情也会发生。您可以向函数传递数量可变的参数,但这是一个单独的主题,所以让我们集中讨论选项2。在这种情况下,数据结构应该是指向对象的指针数组

    好的,那么当你的东西有一个复杂的类型,比如数组(指向返回数组指针的函数的数组,或者其他什么)时,你怎么创建一个呢?答案很简单:使用typedef

    typedef int MyThing[2][2]; // could be anything
    MyThing one = {{1,2},{3,4}};
    MyThing two = ...; // etc
    
    MyThing* manyPointersToThings[] = {&one, &two};
    
    void myFunc(int nThings, MyThing things[nThings]) {
    
       // in here, each things[i] is a *pointer* to MyThing
       (*things[0])[1][2] = 42;
        // whatever
    }
    
    这适用于任何类型的事情。如果您的对象实际上是一个数组,那么还有另一种选择:您的数据结构可以存储指向数组第一个元素的指针,而不是指向数组本身的指针

    typedef int MyThing[2]; // this type names an *element* of your array
    MyThing one[2] = {{1,2},{3,4}};
    MyThing two[2] = ...; // etc
    
    MyThing* manyPointersToThings[] = {one, two}; // note no & here
    
    void myFunc(int nThings, MyThing things[nThings]) {
    
       // in here, each things[i] is a pointer to the first element of an array
       things[0][1][2] = 42;
        // whatever
    }
    
    使用此选项,您可以获得一些灵活性,因为您的阵列不必都具有相同的大小。你也失去了括号中丑陋的取消引用

    为完整起见,以下是相同函数的原型:

    void myFunc(int nThings, int (*things[nThings])[2][2]) // version 1
    void myFunc(int nThings, int (*things[nThings])[2]) // version 2
    
    这些版本比typedef版本灵活一些,因为现在可以使用变量(另一个参数)而不是硬编码的数字2


    如果您在写下上述内容时遇到困难,请尝试。

    不幸的是,这并不能回答我的问题。让我们接受你的答案,但修改它,以便我通过多个
    a
    。可能每个
    a
    都生活在一个数组中,也可能在堆中。如何更新您的
    myfunc
    签名,以便编译器知道每个
    a
    的维度?非常感谢,这看起来很有希望!然而,我有点偏执,因为二维数组的数量和维数相等。也就是说,我怀疑
    (**p)[2]
    并不表示外部数组的长度为2(
    a
    b
    ),而不是表示最内部的维度为
    2
    。因此,我对它是如何work@AntiEarthI[2]表示数组a和b的第二个(最右边的)维度,由于
    *p[]
    周围的括号,它们被声明为例如int a[2][2]Ahh!所以
    int**p[2]
    读作“最外层有dim2”,但
    int(**p)[2]
    读作“最内层有dim2”?这真的很有帮助,非常感谢!
    typedef int MyThing[2][2]; // could be anything
    MyThing one = {{1,2},{3,4}};
    MyThing two = ...; // etc
    
    MyThing* manyPointersToThings[] = {&one, &two};
    
    void myFunc(int nThings, MyThing things[nThings]) {
    
       // in here, each things[i] is a *pointer* to MyThing
       (*things[0])[1][2] = 42;
        // whatever
    }
    
    typedef int MyThing[2]; // this type names an *element* of your array
    MyThing one[2] = {{1,2},{3,4}};
    MyThing two[2] = ...; // etc
    
    MyThing* manyPointersToThings[] = {one, two}; // note no & here
    
    void myFunc(int nThings, MyThing things[nThings]) {
    
       // in here, each things[i] is a pointer to the first element of an array
       things[0][1][2] = 42;
        // whatever
    }
    
    void myFunc(int nThings, int (*things[nThings])[2][2]) // version 1
    void myFunc(int nThings, int (*things[nThings])[2]) // version 2