Инициализация на 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 **, без да се налага да минавам през всички модата на циклите for или копирането на статично разпределения масив в динамично разпределен.

Ще свърши ли работа следното?

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

Има ли по-хубав начин от този да го направите?

Благодаря на всички.

P.s. Знам, че в реалния живот бихме прочели стойности от DB или файл в динамично разпределени масиви и избягвахме всички тези неща.


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

Обмислям да премина от Eclipse към Intellij. Едно нещо, което харесвам в Eclipse е, че цялата инсталация е само папка и мога да я поставя на USB памет и да я копирам на друг компютър, ако искам. Всички мои добавки, настройки и всичко останало идват с мен и всичко, което трябва да направя, е просто да копирам папка.

Има ли някакъв начин да направя това с Intellij?

- 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