Intereting Posts
Выделение большого массива (5000+) win32 C / C ++ считывает данные из «заблокированного» файла Проверка того, пуст ли массив структур или нет Инициализация против назначения в C Команды -L и -l не работают в Makefile Доступ к статическим переменным, которые моделируют переменные classа из модульных тестов Включение файла заголовка из другого каталога Какое общее неопределенное / неуказанное поведение для C, с которым вы столкнулись? Как бы вы узнали, растет ли стек в машине вверх или вниз? (ДЖАВА) setuid () перед вызовом execv () в vfork () / clone () Вложенная инициализация переменных структуры измерять время для выполнения одной инструкции Является ли #if определенным MACRO эквивалентным #ifdef MACRO? который является лучшим способом генерировать выбор из заданного набора чисел? Можем ли мы использовать static_assert для обнаружения заполнения в структуре?

Передача многомерного массива в функцию C

У меня возникают проблемы с передачей многомерного массива в функцию в C. Как в typedef, так и в том, что должно быть аргументом.

В настоящее время моя функция def выглядит так:

int foo(char *a, char b[][7], int first_dimension_of_array); 

Я объявляю массив следующим образом:

 char multi_D_array[20][7]; 

Когда я пытаюсь вызвать функцию следующим образом:

 foo(d, multi_D_array, 20); 

Я получаю предупреждение о том, что второй аргумент функции является несовместимым типом указателя. Я пробовал многие из вариантов, которые я видел в Интернете, но все еще не могу понять это правильно. Кроме того, при использовании GDB я нахожу, что передается только первый массив 2D-массива. Обратная связь с тем, что я делаю неправильно, будет с благодарностью оценена.

Большое предупреждение: Обычно я не обрабатывал многомерные массивы.

Я попробовал это только для проверки, но это:

 #include  int foo(char b[][7]) { printf("%d\n", b[3][4]); return 0; } int main(int argc, char** argv) { char multi_d_arr[20][7]; multi_d_arr[3][4] = 42; foo(multi_d_arr); return 0; } 

Компилирует и запускает без каких-либо проблем, используя gcc -Wall . Я не уверен, честно говоря, как второй аргумент можно считать несовместимым типом указателя. Работает отлично.

Однако, так как вы спрашиваете, как мне обращаться с 2-D массивами? Лучше всего использовать указатели:

 char** array2d = malloc((MAX_i+1)*sizeof(char*)); for ( i = 0; i < (MAX_i+1); i++ ) { array2d[i] = malloc((MAX_j+1)*sizeof(char)); } 

Теперь, чтобы быть ясным, наибольший элемент, к array2d[MAX_i][MAX_j] вы можете получить доступ, - array2d[MAX_i][MAX_j] .

Не забывайте инвертировать процесс, когда это делается:

 for ( i = 0; i < (MAX_i+1); i++ ) { free(array2d[i]); } free(array2d); 

Теперь, используя этот метод, нотация индекса остается в силе, поэтому array2d[x][y] прежнему обращается к правильному значению. Буквально, array2d - массив указателей, и каждый array2d[i] .

Почему это лучший метод? Ну, вы можете иметь подматрицы переменных размеров, если хотите. Все, что вам нужно сделать, это изменить цикл for. Этот метод часто используется для массивов строк, в частности, в сигнатуре приложения int main(int argc, char** argv) . argv - массив массива строк переменной длины. Используйте strlen() чтобы определить их длину.

Можете ли вы передать это? Конечно. Вы только что получили его в основном, для начала, но вы также можете написать свою подпись функции так:

 int foo(char** ar2d, const unsigned int size); 

и назовите его:

 char** somearray; /* initialisation of the above */ foo(ar2d, thesizeofar2d); /* when done, free somearray appropriately */ 

Чтобы быть понятным, ваш метод включения параметров размера (например, const unsigned int size ) является очень хорошей практикой, и вы должны придерживаться его.

Высказывания объявлений и функций, которые вы указали в своем вопросе, являются совершенно правильными C и не дают предупреждения с gcc.

Вы уверены, что скопировали проблемный код?

Ну, по определению это несовместимо.

char[20][7] не совпадает с char[][7]

просто избавиться от предупреждения.

И он не передает «только первый массив 2D-массива», он передает только один указатель на массив (указатель на первый элемент или на начало массива). Вы можете увидеть только первые 7 элементов в GDB, потому что на основе типа массива внутри функции GDB знает только 7 элементов.

Ваш код отлично работает для меня? Вот мой тестовый код: http://codepad.org/wSppLiwl

Начиная с C99 вы можете иметь массивы переменной длины и делать такие вещи, как показано ниже. В основном предоставленный параметр для массива измерений используется для объявления размера массива. Скорее всего, это лучший подход для современных компиляторов.

 #include  int foo(char *a, int fdim, char b[fdim][7]){ printf("b[19][6] = %d\n", b[19][6]); return 0; } int main(){ char d[10]; char multi_D_array[20][7]; int x, y; for (x = 0 ; x < 7 ; ++x){ for (y=0 ; y < 20 ; ++y){ multi_D_array[y][x] = y + x; } } foo(d, 20, multi_D_array); } 

Даже если это относится и к C ++, вас также может заинтересовать, читая мои ответы там и там (и, конечно же, ответы других), чтобы лучше понять C-массивы.

Суть в том, что C / C ++ не справляется с многомерными массивами. В большинстве случаев проще иметь это одномерный массив и выполнять колонку строк, обращаясь к себе.