Передача 2D массивов в C - PullRequest
       10

Передача 2D массивов в C

0 голосов
/ 03 октября 2010

Я взял паузу в C и снова возвращаюсь к ней.

Если я хочу создать двумерный массив пар, я могу сделать это двумя способами:

double** m_array = (double**) malloc(2*sizeof(double*));
double*  m_array = (double*)  malloc(2*sizeof(double));

ИЛИ

double array[2][2];

Но, когда я хочу передать массив malloc против другого, кажется, есть два соглашения:

//allowed for passing in malloc'd array, but not for other array
func_m(m_array) //allowed
func_m(array) //disallowed
func_m(double** m_array)

//allowed for passing in either array; required for passing in non-malloc'd array
func(m_array) //allowed
func(array) //allowed
func(double array[][2])

Во-первых, мне не нужна никакая информация, кроме того, что это указатель на массив указателей.Но это может быть только массив malloc.

Во втором случае мне нужно передать длину каждого массива, на который указывает массив double *.Это кажется глупым.

Я что-то упустил?Заранее спасибо.

Ответы [ 5 ]

6 голосов
/ 03 октября 2010

Первый вообще не создает 2-D массив. Он создает массив указателей, которые, очевидно, нигде не указывают. Если бы вы инициализировали каждый указатель как массив, это все равно был бы массив массивов, а не двумерный массив.

Почему бы вам просто не создать двумерный массив?

double* dynamicArray = malloc(rows * columns * sizeof (double));

или

double autoArray[rows][columns];

и затем вы можете использовать любой из них с этой функцией:

void func(double* array, size_t rows, size_t columns);
2 голосов
/ 03 октября 2010

Для уточнения предположим, что вы заявляете:

int my_static_array[row][col];

Какой тип my_static_array против массива malloc (назовем его массивом my_malloc) в ответе pmg? my_static_array - это непрерывная строка * col * sizeof (int) числа байтов в памяти, с указателем int * на ее начало. При вычислении my_static_array [x] [y] компилятор знает, что делать (потому что они хранятся в мажорном порядке ):

*(addr(my_static_array) + [sizeof(int)*col*x] + [sizeof(int)*y])

Вот почему мне нужно передать значение col для C:

(1) func(int my_static_array[][col])
(2) func(int my_static_array[][])

В (1) компилятор знает, как правильно рассчитать адрес для статического массива. В (2) компилятору не хватает информации. Вот почему (1) компилируется, а (2) не будет.

Однако, если это массив malloc, можно передать:

func(int** my_malloc_array)

Поскольку это указатель на непрерывный массив одномерных массивов, компилятору не требуется помощь. my_malloc_array [x] [y] выполняется просто:

*(*(addr(my_malloc_array)+x)+y)

Компилятору не нужна никакая другая информация о его размерности для вычисления.

Итак, какой урок? 2D-массивы NOT совпадают с массивом указателей на одномерные массивы. Первый имеет тип int (* my_static_array) [row * col] - указатель на массив row * col элементов, последний имеет тип int ** - указатель на массив row указатели.

0 голосов
/ 05 октября 2010

Используйте простой typedef:

typedef double Twodouble_t[2];

void func(Twodouble_t *ptr)
{
  size_t i, numelements = sizeof*ptr/sizeof**ptr;
  puts("first array");
  for( i=0; i<numelements; ++i )
    printf("\n%f",ptr[0][i]);
}
...
Twodouble_t array[]={ {1., 1.},{2., 2.},{3.,3.} };
func(array);
...
0 голосов
/ 03 октября 2010

Предположим, что память компьютера представляет собой хранилище, заполненное последовательно пронумерованными ящиками.Когда вы делаете

int matrix[10][3];

, вы резервируете 30 ящиков для хранения значений матрицы (скажем, от 131 до 160 включительно).

Теперь предположим, что вы хотите суммировать все значения в матрицев функции:

int matrix_sum(int matrix[10][3]) { /* ... */ }

, но вся функция, полученная (в соответствии со стандартом), является указателем на первый элемент матрицы: указатель на массив 3 int с.Таким образом, функция знает, что блоки 131, 132 и 133 принадлежат матрице, но она не знает, какова длина матрицы на самом деле.

0 голосов
/ 03 октября 2010

Ваше распределение для 2D-массива неверно.Обычный двухмерный способ:

double **m_array = malloc(NROWS * sizeof *m_array);
for (i = 0; i < NROWS; i++) {
  m_array[i] = malloc(NCOLS * sizeof *m_array[i]);
}

При передаче массивов или указателей (любых измерений) в функции вы должны сообщить функции размеры: они не закодированы в массиве или самих указателях.

С одной стороны, у вас есть указатели (на указатели (на указатели (...))) на некоторые, а с другой стороны, у вас есть массивы (массивов (массивов (...))) некоторыхtype.

Когда вы передаете указатель на функцию, это именно то, что происходит.Когда вы «передаете массив», происходит то, что массив превращается в указатель на свой первый элемент.Итак,

foo(array); // is the same as foo(&(array[0]));

, а когда array является многомерным массивом, тип затухающего указателя равен pointer to array[size] of SOMETHING (но вы не можете использовать этот размер!).

Простой способвыход состоит в том, чтобы написать свои функции с простым указателем и передать умножение всех измерений

double array[3][4][5];
foo(&(array[0][0][0]), 3*4*5);
...