有很多类似的问题,但我仍然找不到任何与C99/C11中可变长度数组特征相关的答案.
如何将多维可变长度数组传递给C99/C11中的函数?
例如:
void foo(int n, int arr[][]) // <-- error here, how to fix?
{
}
void bar(int n)
{
int arr[n][n];
foo(n, arr);
}
Run Code Online (Sandbox Code Playgroud)
编译器(g++-4.7 -std=gnu++11)说:
error: declaration of ‘arr’ as multidimensional array must have bounds for all dimensions except the first
如果我改成它int *arr[],编译器仍抱怨:
error: cannot convert ‘int (*)[(((sizetype)(((ssizetype)n) + -1)) + 1)]’ to ‘int**’ for argument ‘2’ to ‘void foo(int, int**)’
下一个问题,如何通过值传递它以及如何通过引用传递它?显然,通常你不希望在将它传递给函数时复制整个数组.
对于常量长度数组,它很简单,因为正如"常量"所暗示的那样,在声明函数时应该知道长度:
void foo2(int n, int arr[][10]) // <-- ok
{
}
void bar2()
{
int arr[10][10];
foo2(10, arr);
}
Run Code Online (Sandbox Code Playgroud)
我知道,将数组传递给这样的函数不是最佳实践,我根本不喜欢它.使用平面指针或对象(如std:vector)或其他方式可能更好.但是,从理论的角度来看,我有点好奇这里的答案是什么.
Kos*_*Kos 46
将数组传递给函数在C和C++中有点滑稽.没有数组类型的右值,所以你实际上传递了一个指针.
要处理2D数组(实数,不是数组数组),您需要传递2个数据块:
这些是两个独立的值,无论是C或C++,还是VLA或没有或什么都没有.
最简单,无处不在,但需要更多的手工工作
void foo(int width, int* arr) {
arr[x + y*width] = 5;
}
Run Code Online (Sandbox Code Playgroud)
VLA,标准C99
void foo(int width, int arr[][width]) {
arr[x][y] = 5;
}
Run Code Online (Sandbox Code Playgroud)
VLA w /反向参数,前向参数声明(GNU C扩展)
void foo(int width; int arr[][width], int width) {
arr[x][y]=5;
}
Run Code Online (Sandbox Code Playgroud)
C++ w/VLA(GNU C++扩展,非常难看)
void foo(int width, int* ptr) {
typedef int arrtype[][width];
arrtype& arr = *reinterpret_cast<arrtype*>(ptr);
arr[x][y]=5;
}
Run Code Online (Sandbox Code Playgroud)
带有2D数组的[x] [y]表示法有效,因为数组的类型包含宽度.没有VLA =数组类型必须在编译时修复.
因此:如果你不能使用VLA,那么......
如果你可以使用VLA(C99或GNU C++扩展),那么......
对于C++,boost::multi_array是一个不错的选择.
对于2D阵列,您可以进行两次单独的分配:
T(A)的一维指针数组T(B)然后将(A)中的指针设置为指向(B)的各行.
使用此设置,您可以简单地传递(A),T**并且它将在[x][y]索引方面表现良好.
这个解决方案适用于2D,但需要越来越多的样板来实现更高的尺寸.由于额外的间接层,它也比VLA解决方案慢.
您也可能遇到类似的解决方案,每个B行都有单独的分配.在C语言中,它看起来像一个malloc-in-a-loop,类似于C++的向量向量.然而,这消除了将整个阵列放在一个块中的好处.
| 归档时间: |
|
| 查看次数: |
33833 次 |
| 最近记录: |