main. c: предупреждение: передача аргумента '' из несовместимого типа указателя - PullRequest
2 голосов
/ 16 апреля 2020

Я пытаюсь передать и вернуть двумерный динамический массив c по параметру, однако он всегда показывает предупреждение, о котором я упоминал в вопросе. Я знаю, что что-то не так с параметром массива, но я не смог найти ни в одной книге или на веб-сайте, как правильно передать массив, размеры которого меняются. Я читал похожие вопросы к моему предупреждению, и это в основном о добавлении & в вашем указателе, который я не добавил в моем.

#include <stdio.h>
#include <stdlib.h>

void fun(int m, int n, int (*arr)[n]);

int main(void) {
    int i, j, m, n, **arr;
    printf("Enter the dimensions m, n\n");
    scanf("%d %d", &m, &n);
    arr = (int **)malloc(m * sizeof(int *));
    for (i = 0; i < m; i++) {
        arr[i] = (int *)malloc(n * sizeof(int));
    }
    fun(m, n, *arr);
    printf("\n\n");
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            printf("%5d", arr[i][j]);
        }
        printf("\n");
    }
    if (arr == NULL) {
        exit(1);
    } else
    if (arr != NULL) {
        free(arr);
    }
    return 0;
}

void fun(int m, int n, int (*arr)[n]) {
    int i, j, k = 0;
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            k = k + 1;
            arr[i][j] = k;
        }
    }
}

Ответы [ 3 ]

7 голосов
/ 16 апреля 2020
int **arr;

В main, arr - это указатель на указатель на целое число, и вы заполняете его выделением вложенной памяти, потому что задействованы два уровня указателей. arr[i] может быть фрагментирован, и каждый может содержать различное количество записей, что делает arr «рваным» массивом.

int (*arr)[n]

Аргументом для вашей функции является указатель на массив n целые числа. Здесь записи arr непрерывны в памяти, так что arr[0] и arr[1] разделяются sizeof(int[n]) байтами.

Это разные типы, и компилятор говорит вам об этом. Выберите один.

A Вы можете придерживаться подхода «указатель-указатель». Тогда ваша подпись функции должна соответствовать определению в main:

void fun(int m, int n, int **arr) ...

. В этом случае вы также должны free all arr[i] в конце, до free(arr).

B В качестве альтернативы, вы можете сохранить свою функцию curret и создать непрерывный массив с одним выделением:

int (*arr)[n] = malloc(m * sizeof(*arr));

Затем передать его в вашу функцию напрямую, без разыменования:

fun(m, n, arr);

В конце просто free(arr).

1 голос
/ 16 апреля 2020

fun определяется как получение указателя на массив переменного размера или n int. Это синтаксис C 10 c, который может не поддерживаться некоторыми компиляторами C. Вы также могли бы определить fun с более простым и более читаемым прототипом, который фактически эквивалентен:

void fun(int m, int n, int arr[m][n]);

Также эквивалентен этому:

void fun(int m, int n, int arr[][n]);

Проблема заключается в том, что вы выделяете совсем другой тип объекта: массив m указателей на массивы n int. Вместо этого вы должны выделить массив m массивов переменного размера n int и сохранить его адрес в указателе с соответствующим типом:

int (*arr)[n] = malloc(m * sizeof(*arr));

Или просто определить его как двумерную переменную размером массив с автоматами c хранилище:

int arr[m][n];

Если выделить с помощью malloc(), вы освободите объект с помощью

free(arr);

Вот модифицированная версия:

#include <stdio.h>
#include <stdlib.h>

void fun(int m, int n, int arr[m][n]);

int main(void) {
    int i, j, m, n;

    printf("Enter the dimensions m, n\n");
    if (scanf("%d %d", &m, &n) != 2 || m <= 0 || n <= 0)
        return 1;

    int (*arr)[n] = malloc(m * sizeof(*arr));
    if (arr == NULL)
        return 1;

    fun(m, n, arr);

    printf("\n\n");
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            printf("%5d", arr[i][j]);
        }
        printf("\n");
    }
    free(arr);
    return 0;
}

void fun(int m, int n, int arr[m][n]) {
    int i, j, k = 0;
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            k = k + 1;
            arr[i][j] = k;
        }
    }
}
1 голос
/ 16 апреля 2020

Вы передаете указатель на int (то есть * arr), но вы объявили функцию, которая получит указатель на массив из n целых чисел.

Итак, просто внесите следующие изменения:

void fun(int m, int n, int **arr); // also change where function definition begins
fun(m, n, arr);

Кстати, освобождение памяти не завершено.

for (i=0; i<m; i++)
  free(arr[i]); // first free individual array elements
free(arr);
...