2013-02-15 2 views
5

У меня проблема, когда я пытаюсь передать указатель массива (который содержит параметры, необходимые для некоторых функций в моей программе) для структуры, которая затем должна быть передана этим функциям. GSL, например, хочет, чтобы я передавал параметры таким образом.Как передать указатель статического 2D-массива в структуру/класс?

Небольшой пример программы выглядит следующим образом:

#include <iostream> 

using namespace std; 

struct myparams 
{ 
    double * a; 
    double ** b; 
}; 

int main() 
{ 
    double c[10] = {0,1,2,3,4,5,6,7,8,9}; 
    double d[4][3] = {{1,2,3},{4,5,6},{7,8,9},{10,11,12}}; 

    double** e = new double*[4]; 
    for (int i = 0; i < 4; i++) { 
     e[i] = new double[3]; 
    } 

    myparams params; 

    // THIS WORKS: 
    params.a = c; 
    for (int i = 0; i < 10; i++) { 
     cout << params.a[i] << endl; 
    } 

    // THIS DOESN'T WORK 
    params.b = d; 

    // THIS WORKS: 
    params.b = e; 

    delete[] e; 
} 

В чем проблема с

params.b = d 

Компилятор жалуется "cannot convert 'double[4][3]' to 'double**' in assignment" или что-то подобное (в переводе с немецкого).

+1

'double [n] [m]' не может распасться на 'double **', тогда как 'double [n]' может распасться на 'double *'. Вот почему первое задание действительно, а последнее - нет. – Zeta

+0

Также см. Http://stackoverflow.com/a/13273979/560648 и http://stackoverflow.com/a/9557855/560648 и http://stackoverflow.com/a/7139014/560648 –

+0

Кроме того, никогда не говорите " это не работает "снова! –

ответ

7

double d[4][3]; представляет собой массив массивов. double b**; - указатель на указатель. Эти типы не совпадают (обычные «массивы - это просто указатели», которые вы, возможно, читали в Интернете, - это неправильный).

Элементы d имеют тип double[3]. Массивы, когда их обходят, распадаются на указатели на их первый элемент (см. Раздел 4.2 стандарта C++). d будет распадаться до double(*)[3] (указатель на массив из 3 двухместных).

Краткая история, double(*)[3] не конвертируется в double**, и это то, что говорит вам компилятор.

Если вам нужно сохранить d, так как это необходимо, вам необходимо объявить b как double (*b)[3];

Для более подробного описания работы, обратитесь к this SO question.

+0

Спасибо! Это было почти решение. Это не 'double (* b) [4]', а 'double (* b) [3]'. – GriffinPeterson

+0

Мне нравится, как вы приняли неправильный ответ над правильным. В этом есть смысл. –

+0

@LightnessRacesinOrbit Если вы укажете, что неправильно, я исправлю это. Спасибо. – jrok

6

Это потому, что указатель на указатель (или массив указателей, как он может быть использован в качестве) не то же самое, как массив массивов. Макет в памяти несовместим.

Например, предположим, что у нас есть эти два объявления:

char aa[2][2] = { { 'a', 'b' }, { 'c', 'd' } }; 
char **pp; 

pp = new char*[2]; 
pp[0] = new char[2]; 
pp[1] = new char[2]; 

Массив aa выглядит в памяти:

+----------+----------+----------+----------+ 
| aa[0][0] | aa[0][1] | aa[1][0] | aa[1][1] | 
+----------+----------+----------+----------+ 

"массив" pp тем временем выглядит следующим образом:

+------+------+ 
| a[0] | a[1] | 
+------+------+ 
    |  | 
    |  v 
    |  +---------+---------+ 
    |  | a[0][0] | a[0][1] | 
    |  +---------+---------+ 
    V 
    +---------+---------+ 
    | a[0][0] | a[0][1] | 
    +---------+---------+ 

"массив" pp содержит точку ERS в другой «массив»

+0

+1: Абсолютно правильно. –

+0

Благодарим за быстрый ответ! Но какой член мне нужен в моей структуре 'myparams' для хранения указателя на массив' d'? – GriffinPeterson

+0

Хорошо, я думаю, это лучше, чем [моя диаграмма] (http://stackoverflow.com/a/7139014/560648). Проклятье. –

Смежные вопросы