zac*_*ack 2 c++ multidimensional-array
我有一个函数,它将指针指针作为参数.
func(double **arr, int i);
Run Code Online (Sandbox Code Playgroud)
在main函数中,数组的定义如下:
double arr[][] = //some initialization here;
Run Code Online (Sandbox Code Playgroud)
如何从主代码中调用此函数.我尝试了以下但它给出了一个错误
func (&arr);
Run Code Online (Sandbox Code Playgroud)
不行.任何帮助将非常感激.谢谢
Pav*_*aev 16
类型arr
是double[X][Y]
- 也就是说,Y个X的X数组的数组 - 在哪里X
并Y
依赖于你的初始化器.这是不一样的指针类型.但是,根据C转换规则,数组可以衰减为指向其元素的指针.在你的情况下,由这种衰减产生的类型将是double(*)[Y] - 指向Y双精度数组的指针.请注意,这是一个指向数组的指针,而不是一个指针数组,所以它不会再进一步衰减.此时,您会遇到类型不匹配,因为您的函数需要double**
.
处理此问题的正确方法是将数组视为一维,并传递宽度.所以:
void func(double* arr, int w) {
// arr[2][3]
arr[2*w + 3] = ...;
}
double x[6][8] = { ... };
func(&x[0][0], 8);
Run Code Online (Sandbox Code Playgroud)
特别是在C++中,如果你总是拥有静态分配的众所周知(但不同)类型的数组,你可以使用这样的模板和引用:
template <int W, int H>
inline void func(const double (&arr)[W][H]) {
arr[2][3] = ...;
}
double x[6][8] = { ... };
func(x); // W and H are deduced automatically
Run Code Online (Sandbox Code Playgroud)
但是,当你拥有的只是一个指针时(例如,当数组被new
分配,并且其大小是在运行时计算的时候),这将不起作用.对于最常见的情况,您应该使用C++容器.仅使用标准库,通常使用向量向量:
#include <vector>
void func(std::vector<std::vector<double> > arr) {
arr[2][3] = ...;
}
std::vector<std::vector<double> > x(6, std::vector<double>(8));
x[0][0] = ...;
...
func(x);
Run Code Online (Sandbox Code Playgroud)
如果你可以使用Boost,它有一个非常好的MultiArray库:
void func(boost::multi_array<double, 2> arr) { // 2 means "2-dimensional"
arr[2][3] = ...;
}
boost::multi_array<double, 2> x(boost::extents[6][8]);
x[0][0] = ...;
...
func(x);
Run Code Online (Sandbox Code Playgroud)
[编辑]你说你不能改变你的功能定义.如果是这样,那么它实际上是一个将其参数视为指针数组的函数,因此您应该相应地分配您的数据结构.例如:
double x1[8] = { 1, 2, ... };
double x2[8] = { 3, 4, ... };
...
double* x[6] = { x1, x2, ... };
func(x);
Run Code Online (Sandbox Code Playgroud)
dmc*_*kee 10
A double **p
与a不同double[][] a
,所以你不能把它作为另一个传递.
特别地,二维数组变量是包含双精度的(单个!)内存块,您可以使用[][]
语法访问它们.这要求编译器知道数组的维度,以便它可以计算每个元素的正确偏移量.它也可以透明地衰减到指向该内存块的指针,但这样做会失去对如何以二维数组访问该内存的理解:它实际上变成了一个指向double的指针.
+----+ +---------+---------+---------+
| (a---------->) | a[0][0] | a[0][1] | a[0][2] | ...
+----+ +---------+---------+---------+
| a[1][0] | a[1][2] | ...
+---------+---------+
...
Run Code Online (Sandbox Code Playgroud)
该函数所期望的是一个指向内存块的指针,该内存块包含一个或多个指向包含双精度的附加内存块的指针.
+---+ +------+ +---------+---------+
| p-------->| p[0]------->| p[0][0] | p[0][3] | ...
+---+ +------+ +---------+---------+
| p[1]--\
+------+ \ +---------+---------+
... --->| p[1][0] | p[1][4] | ...
+---------+---------+
Run Code Online (Sandbox Code Playgroud)
虽然语法看起来很相似,但这两种结构具有完全不同的语义.
更完整的讨论,请参阅我的回答到前面的问题(实际上地址C,但问题是相同的).