I have a function that takes a pointer to a pointer an as argument.
func(double **arr, int i);
where in the main function the array is defined as follows:
double arr[][] = //some initialization here;
How can I call this function from my main code. I tried the following but it gives an error
func (&arr);
Doesn't work. Any help would be much appreciated. Thanks
The type of arr is double[X][Y] - that is, an array of X arrays of Y doubles - where X and Y depend on your initializers. This is not the same as pointer type. However, according to C conversion rules, an array can decay into a pointer to its element. In your case, the type resulting from such decay will be double(*)[Y] - a pointer to an array of Y doubles. Note that this is a pointer to array, not an array of pointers, so it will not decay any further. At this point, you get a type mismatch, since your function expects double**.
The correct way to handle this is to treat the array as single-dimensional, and pass width along. So:
void func(double* arr, int w) {
// arr[2][3]
arr[2*w + 3] = ...;
}
double x[6][8] = { ... };
func(&x[0][0], 8);
In C++ in particular, if you always have statically allocated arrays of well-known (but different) types, you may be able to use templates and references like this:
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
However, this won't work when all you have is a pointer (e.g. when the array is new-allocated, and its size is calculated at runtime). For the most general case, you should use C++ containers instead. With standard library only, one typically uses vector of vectors:
#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);
If you can use Boost, it has a very nice MultiArray library in it:
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);
[EDIT] you say that you cannot change the definition of your function. If so, then it really is a function treating its argument as an array of pointers, so you should just allocate your data structure accordingly. For example:
double x1[8] = { 1, 2, ... };
double x2[8] = { 3, 4, ... };
...
double* x[6] = { x1, x2, ... };
func(x);
A double **p is not the same thing as a double[][] a, so you can't pass one as the other.
In particular the two-dimensional array variable is a (single!) block of memory containing doubles which you can access with the [][] syntax. This requires that the compiler know the dimension of the array, so that it can compute the correct offset to each element. It can also decay transparently to an pointer to that block of memory, but doing so loses the understanding of how to access that memory as a two dimensional array: it becomes effectively a pointer to double.
+----+ +---------+---------+---------+
| (a---------->) | a[0][0] | a[0][1] | a[0][2] | ...
+----+ +---------+---------+---------+
| a[1][0] | a[1][2] | ...
+---------+---------+
...
The thing expected by the function is a pointer to a block of memory which contains one or more pointers to additional blocks of memory containing doubles.
+---+ +------+ +---------+---------+
| p-------->| p[0]------->| p[0][0] | p[0][3] | ...
+---+ +------+ +---------+---------+
| p[1]--\
+------+ \ +---------+---------+
... --->| p[1][0] | p[1][4] | ...
+---------+---------+
While the syntax looks similar, these two structures have totally different semantics.
For a more complete discussion, see my answer to a previous questions (which actually address c, but the issues are the same).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With