Передача многомерного массива в функцию C - PullRequest
3 голосов
/ 20 января 2011

У меня проблемы с передачей многомерного массива в функцию на 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-массива. Мы будем очень благодарны за отзывы о том, что я делаю неправильно

Ответы [ 6 ]

5 голосов
/ 20 января 2011

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

Я пытался это просто проверить, но это:

#include <stdio.h>

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].

Не забудьте инвертировать процесс, когда закончите:

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(), чтобы определить их длину.

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

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) является очень хорошей практикой, и вам следует придерживаться его.

1 голос
/ 20 января 2011

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

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

0 голосов
/ 20 января 2011

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

#include <stdio.h>

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.

0 голосов
/ 20 января 2011

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

char[20][7] - это не то же самое, что char[][7]

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

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

0 голосов
/ 20 января 2011

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

0 голосов
/ 20 января 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...