Почему я не могу использовать int arr [2] [2] в качестве параметра? - PullRequest
1 голос
/ 26 сентября 2019
void setArr(int x[2][2], int a, int b)
{
    for (int i = 0; i < a; i++)
        for (int j = 0; j < b; j++)
            x[i][j] = 0;
}
int main(void)
{
    int *arr[2];
    for (int i = 0; i < 2; i++) {
        arr[i] = malloc(sizeof(int) * 2);
    }
    setArr(arr, 2, 2);
}

Я знаю, что этот код не будет работать, но я не знаю причину этого.Может ли кто-нибудь объяснить, почему в этом случае я не могу использовать x [2] [2] в качестве параметра для получения обр.Спасибо

Я поместил код в визуализатор, а функция setArr устанавливает элемент arr в NULL.Я знаю, что NULL равен 0 в C. Но я не могу связать, почему и как элемент arr может быть установлен в NULL.

Ответы [ 3 ]

0 голосов
/ 26 сентября 2019

Объявление функции void setArr(int x[2][2], int a, int b) объявляет setArr как функцию, которая принимает в качестве первого параметра массив из 2 массивов, каждый из которых содержит 2 целых числа.В то время как в main вы объявляете arr (переменная, которую вы передаете setArr) как int *arr[2], то есть как указатель на массив из 2 целых чисел.

Решение состоит в том, чтобы либо изменитьваш код в main, например, объявив arr как int arr[2][2] и удалите цикл for или измените setArr так, чтобы он брал указатель на массив из двух целых чисел void setArr(int *x[2], int a, int b).

Я не уверен, что последний может вызвать какие-либо проблемы (gcc -Wall компилируется без предупреждений), но следует обратить внимание на разницу в расположении памяти при объявлении arr в качестве указателя на массив размера 2 или объявлениеэто как массив из 2 массивов размера 2. Компиляция и выполнение следующего должны показать вам разницу:

    int main(void) {
        int *arr[2];
        for (int i = 0; i < 2; i++) {
            arr[i] = malloc(sizeof(int) * 2); 
        }   
        printf("The address of arr[0] is %p\n", &arr[0]);
        printf("The address of arr[1] is %p\n\n", &arr[1]);
        printf("The address of arr[0][0] is %p\n", &arr[0][0]);
        printf("The address of arr[0][1] is %p\n", &arr[0][1]);
        printf("The address of arr[1][0] is %p\n", &arr[1][0]);
        printf("The address of arr[1][1] is %p\n\n", &arr[1][1]);

        int arr2[2][2]; 
        printf("The address of arr2[0] is %p\n", &arr2[0]);
        printf("The address of arr2[1] is %p\n\n", &arr2[1]);
        printf("The address of arr2[0][0] is %p\n", &arr2[0][0]);
        printf("The address of arr2[0][1] is %p\n", &arr2[0][1]);
        printf("The address of arr2[1][0] is %p\n", &arr2[1][0]);
        printf("The address of arr2[1][1] is %p\n", &arr2[1][1]);

        // setArr(arr, 2, 2); 
}

Запустив исполняемый файл один раз на моей машине, я получил следующее:

The address of arr[0] is 0x7ffe43d226b0
The address of arr[1] is 0x7ffe43d226b8

The address of arr[0][0] is 0xb62010
The address of arr[0][1] is 0xb62014
The address of arr[1][0] is 0xb62030
The address of arr[1][1] is 0xb62034

The address of arr2[0] is 0x7ffe43d226c0
The address of arr2[1] is 0x7ffe43d226c8

The address of arr2[0][0] is 0x7ffe43d226c0
The address of arr2[0][1] is 0x7ffe43d226c4
The address of arr2[1][0] is 0x7ffe43d226c8
The address of arr2[1][1] is 0x7ffe43d226cc

Вы можете видеть, что при объявлении arr в качестве указателя на массив два массива из двух целых не являются смежными , тогда как при объявлении его как массива массивов это так.Более того, при объявлении его как массива массивов нет необходимости динамически выделять память (например, используя malloc).

0 голосов
/ 26 сентября 2019

Может ли кто-нибудь объяснить, почему, в этом случае, я не могу использовать x [2] [2] в качестве параметра для получения обр.

Поскольку вы используете дико разныетипы.int *arr[2]; - это массив из 2 int*, каждый из которых назначен выделенному фрагменту памяти.Это таблица поиска или «зубчатый массив», если хотите, а не правильный 2D-массив.Подробнее см. Правильное распределение многомерных массивов .

Правильный код для размещения двумерного массива:

#include <stdlib.h>

void setArr(int a, int b, int x[a][b])
{
    for (int i = 0; i < a; i++)
        for (int j = 0; j < b; j++)
            x[i][j] = 0;
}

int main(void)
{
    int (*arr)[2] = malloc(sizeof(int[2][2])); 
    setArr(2, 2, arr);
    free(arr);
}

Здесь arr в основном - указательк первому элементу int[2][2].Первый элемент этого двумерного массива - int[2], а указатель на такой элемент - int(*)[2].

0 голосов
/ 26 сентября 2019

x[2][2] - это просто объявление переменной;нет необходимости объявлять переменную во входных данных функции;Вы должны объявить это раньше и просто использовать его адрес:

void setArr(int** x, int a, int b)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...