2010-10-02 5 views
0

Я взял паузу от C и снова возвращаюсь в нее.Передача 2D-массивов в C

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

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

ИЛИ

double array[2][2]; 

Но, когда я хочу передать malloc'd по сравнению с другими, существуют две конвенции:

//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'd.

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

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

+1

Пожалуйста сделайте ваш вопрос более конкретно. –

ответ

6

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

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

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

или

double autoArray[rows][columns]; 

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

void func(double* array, size_t rows, size_t columns); 
+0

Я отменяю свою галочку, потому что ваш код не будет компилироваться. Переменная double * array должна что-то сказать, как долго столбцы так компилятор может правильно вычислить массив [row] [col] (для ** BOTH ** malloc и статический случай). См. Мой попытка ответить ниже. – dougvk

+0

@dougvk: Вот почему в моем примере показано как количество строк, так и столбцов, которые являются всей информацией, необходимой для вычисления правильного смещения для любых координат '(i, j)' в массиве. –

+0

Я понимаю это, но компилятор этого не делает. Кроме того, я спрашивал * почему *, что нужно было сделать (потому что я надеялся пропустить это требование в своем коде). – dougvk

0

Ваше выделение для 2D массива является неправильным. Обычный 2D путь

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

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

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

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

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); 
+0

Да, это все равно не обойтись без необходимости проходить измерение. Почему C требует этого? – dougvk

+0

Это еще не 2-мерный массив, это (возможно, зубчатый) массив массивов. –

2

Для пояснения предположит, что вы объявляете:

int my_static_array[row][col]; 

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

*(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'd массив, однако, можно передать:

func(int** my_malloc_array) 

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

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

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

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

0

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

int matrix[10][3]; 

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

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

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

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

0

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

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); 
... 
Смежные вопросы