C 将多维数组数组的指针传递给函数,并指定边界
假设我有多个(数量可变)的2D数组(甚至可能是可变长度): 我现在想把它传递给一个函数。我不想将二维阵列复制到三维阵列。但是,我希望指定边界,以便函数知道2D数组的尺寸,以便使用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移动到指针中,
[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;
}
如果数组的第一个维度不是固定的,并且是变化的,那么您也可以将数组的第一个维度的数组传递给函数
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