Cannot convert double [] [] to double **

♀尐吖头ヾ 提交于 2019-12-23 13:42:05

问题


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?


回答1:


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.




回答2:


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.




回答3:


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.




回答4:


A 2d array is a continuous area of storage. The function expects a pointer to pointers. These are incompatible.




回答5:


The function expects an array of pointers to arrays; you have an array of arrays. Some options are:

  • change the function to take a more friendly type, perhaps double* pointing to the first element of a contiguous 2-dimensional array; or
  • build a separate array of pointers pointing to each row of your 2-dimensional array; or
  • restructure your data into an array of pointers to arrays.



回答6:


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



回答7:


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++!



回答8:


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.



来源:https://stackoverflow.com/questions/21731524/cannot-convert-double-to-double

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!