Reputation: 2669
I ve got a function that takes 3 parameteres, first one is **double.
normalizeDataZeroMeanUnitSD(double ** trainingActions, int numberOfTrainingActions, int descriptorDimension)
When I call it from main, I am trying to use normalizeDataZeroMeanUnitSD(data, 681, 24); however, I am receiving
cannot convert parameter 1 from 'double [681][24]' to 'double **'
This is how I construct the data array:
fstream infile;
infile.open("gabor\\Data.txt");
double data[681][24];
while (!infile.eof())
{
for(int j=0;j<681;j++)
{
for(int k=0; k<24;k++)
{
infile >> data[j][k];
}
}
}
infile.close();
Is there a way to do the same using **data?
Upvotes: 5
Views: 11665
Reputation: 5369
Use any of the following declarations. Both are equivalent.
NormalizeDataZeroMeanUnitSD(double trainingActions[][24], int numberOfTrainingActions, int descriptorDimension)
NormalizeDataZeroMeanUnitSD(double trainingActions[681][24], int numberOfTrainingActions, int descriptorDimension)
When you declare a 2D array it takes up contiguous memory locations. So you need to specify at least the number of columns (in case of row major architecture).
For row major and column major definitions, have a look at this.
For your edited question, yes you can declare using **data
. Dynamically allocate the data
array. But remember to free it when you're done with it.
double **data=new double*[681];
for (int i=0;i<681;i++)
{
data[i]=new double[24];
}
//do what you want to do
for (int i=0;i<681;i++)
{
delete [] data[i];
}
delete [] data;
Now your function prototype can be like void func(double **pp)
because data
is a pointer not a 2D array.
Upvotes: 3
Reputation: 6332
You could use a template:
template<std::size_t M, std::size_t N>
void normalizeDataZeroMeanUnitSD(double (&trainingActions)[M][N], int descriptorDimension)
{
for( std::size_t m = 0; m < M; ++m )
{
for( std::size_t n = 0; n < N; ++n )
{
trainingActions[m][n] = ...;
}
}
}
But beware of code bloat if you call this with many differently sized arrays.
Upvotes: 4
Reputation: 7881
Yay, I get to rant about this again.
In C++, despite having similar syntax, 2D arrays are NOT jagged arrays. 2D arrays (double foo[681][24]
) are allocated contiguously in memory. When you deference a 2D array (foo[j][i]
) it actually does *(foo+24*i+j). This is all done under the hood. The sizeof(foo)==sizeof(double)*681*24
.
Jagged arrays are (double** bar;
). This is a bunch of different arrays: first, you allocate an array of pointer, 268 members long. Each pointer will point to an array of doubles, 24 elements long. Bar is just a pointer, so sizeof(bar)==sizeof(void*)
.
More annoyingly, 2D arrays (or a static array of any dimension) behave the opposite of all other types in C++ in the following reguard: they are passed implicitly by reference, causing the weird phenomenon below.
void foo(double bar[24][24]) { std::cout << sizeof(bar) << std::endl;}
int main() {
double test[24][24];
std::cout << sizeof(test) << std::endl;//returns sizeof(double)*24*24
foo(test);//returns sizeof(void*), implicitly passed by reference, opossite of the rest of c++!
Upvotes: 3
Reputation: 8687
Here is a constructive answer for how to make it work.
Basically, you need to generate an array that has pointers to each 1D slice of your 2D array.
double data[N][M] = {...};
double *dataPtrs[N];
for(size_t n=0; n<N; ++n) {
dataPtrs[n] = data[n];
}
normalizeDataZeroMeanUnitSD(dataPtrs, N, M); // order of N and M might be wrong
Upvotes: 3
Reputation: 6846
double[][]
is not the same thing as double**
.
double**
is a pointer to pointers.
double[][]
is a 2-dimensional array allocated as continuous storage.
In order to pass a "2-dimensional array" to the function, you need to create an array of pointers to arrays. For example:
double* array_2d[681];
for(unsigned int i=0; i<681; ++i) {
array_2d[i] = new double[24];
}
normalizeDataZeroMeanUnitSD(array_2d, 681, 24);
Remember to later delete[] each element of array_2d
!
Better yet, change normalizeDataZeroMeanUnitSD
to take a reference to std::vector<std::vector<double>>
, and you no longer have to worry about memory management, nor passing the correct dimensions to the function.
Upvotes: 2
Reputation: 254501
The function expects an array of pointers to arrays; you have an array of arrays. Some options are:
double*
pointing to the first element of a contiguous 2-dimensional array; orUpvotes: 3
Reputation: 36896
The error is pretty clear: Datatype double [681][24]
is not the same as double **
. While it's true that double[681]
can decay to a pointer to its first element (thus, double*
), that does not imply that double[681][24]
can decay to double**
.
Think about it this way: double**
implies a pointer to many pointers. But double[][]
does not have ANY pointers in it. At best, an array of ANY dimensions still only has, at very most, one pointer: to the beginning of its contiguous storage.
Upvotes: 6
Reputation: 71999
A 2d array is a continuous area of storage. The function expects a pointer to pointers. These are incompatible.
Upvotes: 3