我有一个函数,我想作为一个参数,一个可变大小的2D数组 .
到目前为止我有这个:
void myFunction(double** myArray){
myArray[x][y] = 5;
etc...
}
我在代码中的其他地方声明了一个数组:
double anArray[10][10];
但是,调用 myFunction(anArray)
会给我一个错误 .
当我传入数组时,我不想复制数组 . 在 myFunction
中所做的任何更改都应该改变 anArray
的状态 . 如果我理解正确,我只想作为参数传入指向2D数组的指针 . 该函数还需要接受不同大小的数组 . 例如, [10][10]
和 [5][5]
. 我怎样才能做到这一点?
12 回答
将2D数组传递给函数有三种方法:
固定尺寸
1. Pass by reference
在C中通过引用传递数组而不丢失维度信息可能是最安全的,因为动态(freestore)数组可能不需要't worry about the caller passing an incorrect dimension (compiler flags when mismatching). However, this isn't;它仅适用于自动(usually stack-living)数组,即维度应在编译时知道 .
2. Pass by pointer
前一个方法的C等价物是通过指针传递数组 . 这不应该与通过数组的衰减指针类型 (3) 混淆,后者是常见的流行方法,尽管不如此安全但更灵活 . 与 (1) 类似,当数组的所有维度都已修复并在编译时已知时,请使用此方法 . 请注意,在调用函数时,应通过衰减
process_2d_array_pointer(a)
传递数组的地址process_2d_array_pointer(&a)
而不是第一个元素的地址 .可变尺寸
这些都是从C继承但不太安全,编译器无法检查,保证调用者传递所需的维度 . 该函数仅保留调用者作为维度传入的内容 . 这些比上述更灵活,因为不同长度的阵列总是可以传递给它们 .
需要记住的是,没有将数组直接传递给C中的函数[在C中它们可以作为引用传递 (1) ]; (2) 正在传递指向数组的指针而不是数组本身 . 始终按原样传递数组成为指针复制操作,由array's nature of decaying into a pointer促进 .
3. Pass by (value) a pointer to the decayed type
虽然允许使用
int array[][10]
,但我不推荐使用上述语法,因为上面的语法清楚地表明标识符array
是指向10个整数数组的单个指针,而这个语法看起来像是自编译器以来的一些安全性当指向第二维不等于10的数组的指针时,可以标记 . 第一个维度是变化的部分,可以省略 . See here for the rationale为什么只允许省略第一个维度 .4. Pass by pointer to a pointer
同样有一个
int *array[10]
的替代语法,它与int **array
相同 . 在这种语法中,[10]
被忽略,因为它衰减成指针,从而变成int **array
. 也许这只是调用者的一个提示,传递的数组应至少有10列,即使这样也需要行数 . 在任何情况下,编译器都不会标记任何长度/大小违规(它只检查传递的类型是否是指向指针的指针),因此需要行和列计数作为参数在这里有意义 .Note: (4)是最安全的选择,因为它几乎没有任何类型检查和最不方便 . 人们无法合法地将2D数组传递给此函数; C-FAQ condemns由于数组扁平化而
int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10);
执行int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10);
的常用解决方法 . 在这种方法中传递数组的正确方法将我们带到了不方便的部分,即我们需要一个额外的(代理)指针数组,其每个元素指向实际的待传递数组的相应行;然后将这个代理传递给函数(见下文);这一切都是为了完成与上述方法相同的工作,这些方法更安全,更清洁,也许更快 .这是一个测试上述功能的驱动程序:
对shengy的第一个建议的修改,你可以使用模板使函数接受一个多维数组变量(而不是存储必须被管理和删除的指针数组):
print语句用于显示数组是通过引用传递的(通过显示变量的地址)
您可以像这样创建一个函数模板:
然后通过R和C获得两个尺寸大小 . 将为每个数组大小创建一个不同的函数,因此如果您的函数很大并且您使用各种不同的数组大小调用它,这可能会很昂贵 . 你可以使用它作为这样的函数的包装器:
它将数组视为一维,并使用算术来计算索引的偏移量 . 在这种情况下,您将定义模板像这样:
anArray[10][10]
不是指向指针的指针,它是一个连续的内存块,适合存储100个double类型的值,编译器知道如何解决因为您指定了维度 . 您需要将其作为数组传递给函数 . 您可以省略初始尺寸的大小,如下所示:但是,这不允许您传递最后一个维度不是十的数组 .
C中最好的解决方案是使用
std::vector<std::vector<double> >
:它几乎同样有效,而且非常方便 .令人惊讶的是,还没有人提到这一点,但你可以简单地模板化任何2D支持[] []语义 .
它适用于任何2D "array-like"数据结构,例如
std::vector<std::vector<T>>
,或用户定义的类型,以最大化代码重用 .单维数组衰减到指向数组中第一个元素的指针指针 . 当2D阵列衰减到指向第一行的指针时 . 所以,函数原型应该是 -
我更喜欢
std::vector
而不是原始数组 .你可以这样做......
你的输出如下......
传递多维数组的一个重要方面是:
First array dimension
无需指定 .必须指定
Second(any any further)dimension
.1.When only second dimension is available globally (either as a macro or as a global constant)
2.Using a single pointer :在这种方法中,我们必须在传递给函数时对2D数组进行类型转换 .
这是矢量矩阵示例的向量
输出:
您可以在C中使用模板工具来执行此操作 . 我做了这样的事情:
这种方法的问题在于,对于您提供的col的每个值,使用模板实例化新的函数定义 . 所以,
实例化模板两次以产生2个函数定义(一个col = 3,另一个col = 5) .
我们可以使用几种方法将2D数组传递给函数: