Передача 2d массива в функцию в C с указателями - PullRequest
0 голосов
/ 12 сентября 2018

Я новичок в C и изучаю указатели.Итак, я хочу передать указатель на 2d массив.Мне удалось заставить его работать, но я все еще получаю следующее предупреждение:

||=== Build: Debug in matriz (compiler: GNU GCC Compiler) ===|
C:\Users\pauli\.dev\c\uvv\matriz\main.c||In function 'main':|
C:\Users\pauli\.dev\c\uvv\matriz\main.c|15|warning: passing argument 1 of 
'printMatriz' from incompatible pointer type [-Wincompatible-pointer-types]|
C:\Users\pauli\.dev\c\uvv\matriz\main.c|4|note: expected 'int * (*)[2]' but 
argument is of type 'int (*)[2][2]'|
C:\Users\pauli\.dev\c\uvv\matriz\main.c||In function 'printMatriz':|
C:\Users\pauli\.dev\c\uvv\matriz\main.c|23|warning: format '%i' expects argument 
of type 'int', but argument 2 has type 'int *' [-Wformat=]|
||=== Build finished: 0 error(s), 2 warning(s) (0 minute(s), 0 second(s)) ===|
||=== Run: Debug in matriz (compiler: GNU GCC Compiler) ===|

Вот мой код:

#include <stdio.h>
#include <stdlib.h>
#define TAM 2
void printMatriz(int *matriz[TAM][TAM]);

int main()
{
    int i, j, matriz[TAM][TAM];
    for(i = 0; i < TAM; i++) {
        for(j = 0; j < TAM; j++) {
            printf("Matriz[%i][%i] = ", i, j);
            scanf("%i", &matriz[i][j]);
        }
    }
    printMatriz(&matriz);
    return 0;
}
void printMatriz(int *matriz[TAM][TAM])
{
    int i, j;
    for(i = 0; i < TAM; i++) {
        for(j = 0; j < TAM; j++) {
            printf("%i\t", matriz[j][i]);
        }
        printf("\n");
    }
}

Ответы [ 4 ]

0 голосов
/ 12 сентября 2018

Я хочу передать указатель двумерного массива

Вы можете передать указатель на первый элемент двумерного массива и получить доступ ко всем элементам, используя этот указатель, например:

#define TAM 2
void printMatrix(int * matrix); //function prototype

void printMatrix(int * matrix)
{
    int i, j;
    for(i = 0; i < TAM; i++) {
        for(j = 0; j < TAM; j++) {
            printf("%i\t", *(matrix + i*TAM + j));
        }
        printf("\n");
    }
}

В вашей основной функции вы бы сделали что-то вроде этого:

int main()
{
    int i, j, matrix[TAM][TAM];
    for(i = 0; i < TAM; i++) {
        for(j = 0; j < TAM; j++) {
            printf("matrix[%i][%i] = ", i, j);
            scanf("%i", &matrix[i][j]);
        }
    }
    printMatrix(&matrix[0][0]); //could also do this other ways (e.g. matrix[0], *matrix) just wanted to make it explicit that you are passing a pointer to the first element of the 2D array 
    return 0;
}

Мне удалось заставить его работать, но я все еще получаю следующее предупреждение:

||=== Build: Debug in matriz (compiler: GNU GCC Compiler) ===|
C:\Users\pauli\.dev\c\uvv\matriz\main.c||In function 'main':|
C:\Users\pauli\.dev\c\uvv\matriz\main.c|15|warning: passing argument 1 of 
'printMatriz' from incompatible pointer type [-Wincompatible-pointer-types]|
C:\Users\pauli\.dev\c\uvv\matriz\main.c|4|note: expected 'int * (*)[2]' but 
argument is of type 'int (*)[2][2]'|
C:\Users\pauli\.dev\c\uvv\matriz\main.c||In function 'printMatriz':|
C:\Users\pauli\.dev\c\uvv\matriz\main.c|23|warning: format '%i' expects argument 
of type 'int', but argument 2 has type 'int *' [-Wformat=]|
||=== Build finished: 0 error(s), 2 warning(s) (0 minute(s), 0 second(s)) ===|
||=== Run: Debug in matriz (compiler: GNU GCC Compiler) ===|

Ваши предупреждения проистекают из неправильного понимания того, как вы определили свою функцию и затем, что вы ее передали.Как уже говорили другие, ваша функция определяется как получение аргумента двумерного массива указателей на целые числа int * matrix[][], и поскольку имя массива само по себе является указателем на начало этого массива, функция хочет aуказатель на указатель (помните, что первый элемент int * matrix[][] будет указателем на int) , но затем вы передаете его &matrix, который равен int * (указатель на int), потому чтопервый элемент двумерного массива matrix является int.

0 голосов
/ 12 сентября 2018

Вы можете позволить себе использовать гораздо меньше звездочек, как это.Обратите внимание, что код печати меняет порядок индексов по сравнению с вашим кодом.

#include <stdio.h>

#define TAM 2
void printMatriz(int matriz[TAM][TAM]);

int main(void)
{
    int matriz[TAM][TAM];

    for (int i = 0; i < TAM; i++)
    {
        for (int j = 0; j < TAM; j++)
        {
            printf("Matriz[%i][%i] = ", i, j);
            if (scanf("%i", &matriz[i][j]) != 1)
            {
                fprintf(stderr, "failed to read an integer\n");
                return 1;
            }
        }
    }

    printMatriz(matriz);
    return 0;
}

void printMatriz(int matriz[TAM][TAM])
{
    for (int i = 0; i < TAM; i++)
    {
        for (int j = 0; j < TAM; j++)
            printf("%i\t", matriz[i][j]);  // Reversed order of i, j
        printf("\n");
    }
}

Пример выполнения:

Matriz[0][0] = 19
Matriz[0][1] = 28
Matriz[1][0] = 30
Matriz[1][1] = 41
19  28  
30  41

Обратите внимание, что при этом используется обозначение C99 для циклов for,Избегая необходимости переменных i и j вне циклов.Если это проблема, восстановите определения переменных вне циклов.

Если вы действительно хотите использовать указатели на матрицы, вы можете использовать любой из этих двух вариантов кода:

#include <stdio.h>

#define TAM 2
void printMatriz(int (*matriz)[TAM]);

int main(void)
{
    int matriz[TAM][TAM];

    for (int i = 0; i < TAM; i++)
    {
        for (int j = 0; j < TAM; j++)
        {
            printf("Matriz[%i][%i] = ", i, j);
            if (scanf("%i", &matriz[i][j]) != 1)
            {
                fprintf(stderr, "failed to read an integer\n");
                return 1;
            }
        }
    }

    printMatriz(matriz);
    return 0;
}

void printMatriz(int (*matriz)[TAM])
{
    for (int i = 0; i < TAM; i++)
    {
        for (int j = 0; j < TAM; j++)
            printf("%i\t", matriz[i][j]);
        printf("\n");
    }
}

Или:

#include <stdio.h>

#define TAM 2
void printMatriz(int (*matriz)[TAM][TAM]);

int main(void)
{
    int matriz[TAM][TAM];

    for (int i = 0; i < TAM; i++)
    {
        for (int j = 0; j < TAM; j++)
        {
            printf("Matriz[%i][%i] = ", i, j);
            if (scanf("%i", &matriz[i][j]) != 1)
            {
                fprintf(stderr, "failed to read an integer\n");
                return 1;
            }
        }
    }

    printMatriz(&matriz);
    return 0;
}

void printMatriz(int (*matriz)[TAM][TAM])
{
    for (int i = 0; i < TAM; i++)
    {
        for (int j = 0; j < TAM; j++)
            printf("%i\t", (*matriz)[i][j]);
        printf("\n");
    }
}

Обратите внимание на различные обозначения, необходимые в последнем примере - в вызове (как в исходном коде) и при использовании матрицы.

0 голосов
/ 12 сентября 2018

Вы можете сделать так:

#include <stdio.h>

#define TAM 2
void printMatriz(int **matriz);

int main(void)
{
    int **matriz=(int**)malloc(sizeof(int)*TAM);

    for (int i = 0; i < TAM; i++)
    {
        matriz[i]=(int*)malloc(sizeof(int)*TAM);
        for (int j = 0; j < TAM; j++)
        {
            printf("Matriz[%i][%i] = ", i, j);
            if (scanf("%i", &matriz[i][j]) != 1)
            {
                fprintf(stderr, "failed to read an integer\n");
                return 1;
            }
        }
    }

    printMatriz(matriz);
    return 0;
}

void printMatriz(int **matriz)
{
    for (int i = 0; i < TAM; i++)
    {
        for (int j = 0; j < TAM; j++)
            printf("%d ", matriz[i][j]);
        printf("\n");
     }
}
0 голосов
/ 12 сентября 2018

Первый ответ Чтобы сделать его указателем, его необходимо заключить в скобки.

При чтении таких определений начинайте с самого глубокого имени и по спирали начинайте с правой стороны, соблюдая приоритет.

void printMatriz(int (*matriz)[TAM][TAM])

Работа изнутри, начиная с имени:

  • имя matriz - это (спираль в скобках) указатель на
  • [TAM] [TAM] массив из двух чисел
  • целых чисел.

Использование исходного кода:

void printMatriz(int *matriz[TAM][TAM])

Работа изнутри:

  • имя matriz - это массив
  • [TAM] [TAM] из двух десятков
  • указателей на
  • целых чисел.

Надеюсь, что в моем снах не так уж многоглаза.

Теперь, когда вы боролись Второй ответ теперь, когда вы немного выкопали.

Использование спецификатора typedef может значительно упростить некоторые определения, инкапсулируя сложность в объявлении typedef.

typedef int matriz_t[TAM][TAM]; /* typedef simplifies referencing code */

void printTypedef(matriz_t *matriz)   /* (note: now a simple pointer) */
{
    int i, j;
    for(i = 0; i < TAM; i++) {
        for(j = 0; j < TAM; j++) {
            printf("%i\t", (*matriz)[j][i]);  /* still need () here */
        }
        printf("\n");
    }
}

int main()
{
    int i, j;
    matriz_t  matriztdef;               /* doesn't get simpler than this */
    for(i = 0; i < TAM; i++) {
        for(j = 0; j < TAM; j++) {
            printf("Matriz[%i][%i] = ", i, j);
            scanf("%i", &matriztdef[i][j]);
        }
    }
    printTypedef(&matriztdef);
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...