Инициализация 2D-массива в C

Я знаю, что это старый каштан, но я хочу, чтобы в моем коде был статически выделен небольшой 2D-массив. Я знаю, как это сделать:

static int A[3][2] = { { 1, 2 }, { 3, 4 }, { 5, 6 } };

Это нормально, и я могу получить доступ ко всем его членам. Однако у меня есть несколько проблем с передачей его функции, например:

void print_matrix(int **a, int r, int c)
{
    int x, y;

    for(x = 0; x < r; x++)
    {
        printf("Row %02d = %#x = ", x, a[x]);

        for(y = 0; y < c; y++)
        {
            printf("%s%d", (0 == y) ? "" : ", ", a[x][y]);
        }
        printf("\n");
    }
}

Во-первых, я не могу просто передать A в функцию, мне нужно привести его к (int **). Поскольку char * является синонимом char [], меня это немного удивило. Во-вторых, происходит сбой, и когда я проверяю отладчик, внутри подфункции a[0] сообщается как 1, а не как указатель на массив целых чисел.

Я знаю, что здесь происходит тайная магия компилятора/языка C. Но все это немного запутанно. Если я попытаюсь инициализировать как:

static int *A[3] = { { 1, 2 }, { 3, 4 }, { 5, 6 } };

Я получаю тонну предупреждений. Чем это отличается от:

static char *S[3] = { "hello", "there", "stackoverflow" };

Помимо вопроса о тайной магии C, которую я почему-то никогда не изучал, несмотря на более чем десятилетие программирования на C :(, я хотел бы знать, как сгенерировать свой массив, чтобы я мог успешно передать его как int ** без необходимости проходить через все fag циклов for или копирование статически выделенного массива в динамически выделенный.

Будет ли работать следующее?

int *A0 = { 1, 2 };
int *A1 = { 3, 4 };
int *A2 = { 5, 6 };
int **A = { A0, A1, A2 };

Есть ли более приятный способ сделать это?

Спасибо всем.

P.S. Я знаю, что в реальной жизни мы бы считывали значения из БД или файла в динамически выделяемые массивы и избегали всего этого.


person AlastairG    schedule 10.12.2010    source источник
comment
Я бы начал с просмотра этого вопроса в C FAQ, а затем весь раздел.   -  person NPE    schedule 10.12.2010


Ответы (3)


Многомерный массив не становится многоуровневым указателем (не знаю подходящего термина). Распадается только одно измерение. Например:

int [20] становится int *; int [20][5] становится int (*)[5] (а не int **); и т.п.

Если есть большое желание использовать многомерные массивы (через синтаксис [r][c]), то придется передать остальные границы (которые должны быть константами). Если нужны границы переменных, я думаю, что лучший вариант — выполнить преобразование индекса вручную (т.е. вместо a[r][c] использовать a[r*C + c]).

person lijie    schedule 10.12.2010
comment
В C99 можно определить такие функции: void f(int c, int a[][c])... или void f(int c, int (*a)[c]).... После этого , вы можете индексировать массив, как и любой другой многомерный массив. - person tiftik; 10.12.2010

int A0[2] = { 1, 2 };
int A1[2] = { 3, 4 };
int A2[2] = { 5, 6 };
int *A[3] = { A0, A1, A2 };

Вы были близки к последнему разделу, но вам нужны немного другие объявления. Полученный A может быть передан как int ** в функцию.

При этом print_matrix(A, 3, 2); выводит:

Row 00 = 0x5eaeda70 = 1, 2
Row 01 = 0x5eaeda68 = 3, 4
Row 02 = 0x5eaeda60 = 5, 6
person benmcclelland    schedule 27.09.2016

Самый быстрый способ — объявить аргумент a как int a[][2].

void print_matrix(int[][2] a, int r, int c);

// and call the function like this:
print_matrix(A, 3, 2);
person Klark    schedule 10.12.2010
comment
это c, так что void print_matrix(int a[][2], <etc>). - person lijie; 10.12.2010