Если вы не полностью осознаете свою основную проблему, проблема в том, что C передает параметры в функции по значению.Это означает, что при передаче параметра функция получает копию переменной, которую она может изменить, но любые изменения теряются при возврате функции.
Одно предупреждение, когда выделенный указатель пройдено.Хотя он по-прежнему передается по значению, а указатель будет иметь свой собственный адрес, очень отличающийся от оригинала, адрес памяти, который он хранит, поскольку его значение будет по-прежнему указывать на тот же адрес, что и в вызывающем.Это ничем не отличается от назначения int a = 5;
и последующей передачи a
в качестве параметра, функция получает копию переменной, но она по-прежнему содержит 5
.
Однако, если вы попытаетесь выделить илиперераспределить так, чтобы адрес указателя был изменен, тогда любые изменения, внесенные в функцию, будут потеряны при возврате и не будут видны в вызывающей стороне.
Как вы справляетесь с этим?
У вас есть два варианта: (1) передать адрес указателю, поэтому любые изменения адреса могут бытьназначенный разыменованному указателю (то есть исходному адресу указателя), или (2) измените тип возвращаемого значения с void
на тип указателя, который должен быть возвращен, и верните вновь распределенный / перераспределенный указатель для назначения в вызывающей стороне.
Например, в вашем случае вам вообще не нужно передавать matrix
в качестве параметра obtn_matrix()
.Вы можете просто использовать опцию (2) выше и изменить тип возвращаемого значения obtn_matrix()
на int **
и return create_matrix (*m, *n);
в конце, например,
int **create_matrix (int m, int n)
{
int **matrix = malloc (m * sizeof *matrix);
if (matrix == NULL) {
perror ("malloc-matrix");
return NULL;
}
for (int i = 0; i < m; i++)
/* use calloc to initialize values zero */
if ((matrix[i] = calloc (n, sizeof **matrix)) == NULL) {
perror ("malloc-matrix[n]");
return NULL;
}
return matrix;
}
/* use pointers as parameters so the updated values of m, n are
* available back in the caller after the function returns. return
* int** for assignment back in the caller. avoids becomming a
* 3-Star Programmer (not a compliment). return NULL on failure.
*/
int **obtn_matrix (int *m, int *n)
{
fputs ("enter number of rows: ", stdout);
if (scanf ("%d", m) != 1) { /* validate ALL user-input */
fputs ("error: invalid number of rows.\n", stderr);
return NULL;
}
fputs ("enter number of cols: ", stdout);
if (scanf ("%d", n) != 1) {
fputs ("error: invalid number of cols.\n", stderr);
return NULL;
}
return create_matrix (*m, *n);
}
Теперь положить его в целом и отметить, что @ bruno объясняет, почему вы должны передать адрес m, n
(например, &m, &n
) в obtn_matrix
(опция (1) выше), чтобы обновленныйзначения m & n
доступны еще в main()
(вызывающий здесь), вы можете сделать что-то вроде:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int **create_matrix (int m, int n)
{
int **matrix = malloc (m * sizeof *matrix);
if (matrix == NULL) {
perror ("malloc-matrix");
return NULL;
}
for (int i = 0; i < m; i++)
/* use calloc to initialize values zero */
if ((matrix[i] = calloc (n, sizeof **matrix)) == NULL) {
perror ("malloc-matrix[n]");
return NULL;
}
return matrix;
}
/* use pointers as parameters so the updated values of m, n are
* available back in the caller after the function returns. return
* int** for assignment back in the caller. avoids becomming a
* 3-Star Programmer (not a compliment). return NULL on failure.
*/
int **obtn_matrix (int *m, int *n)
{
fputs ("enter number of rows: ", stdout);
if (scanf ("%d", m) != 1) { /* validate ALL user-input */
fputs ("error: invalid number of rows.\n", stderr);
return NULL;
}
fputs ("enter number of cols: ", stdout);
if (scanf ("%d", n) != 1) {
fputs ("error: invalid number of cols.\n", stderr);
return NULL;
}
return create_matrix (*m, *n);
}
void prnt_matrix (int **matrix, int m, int n)
{
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++)
printf (" %4d", matrix[i][j]);
putchar ('\n');
}
}
void free_matrix (int **matrix, int m)
{
for (int i = 0; i < m; i++)
free (matrix[i]); /* free integers */
free (matrix); /* free pointers */
}
int main (void) {
int **matrix, m = 0, n = 0;
if ((matrix = obtn_matrix (&m, &n)) == NULL)
return 1;
prnt_matrix (matrix, m, n);
free_matrix (matrix, m);
return 0;
}
Поскольку вы "didn't share the filler function"
, приведенный выше код просто обнуляет все целочисленные значения, выделяяцелые числа для каждого row
с calloc
вместо malloc
, что является хорошей идеей при работе с симулируемыми массивами, так что если вы случайно не смогли инициализировать одно из целых чисел, вы не будете использовать SegFault при попытке пройти все элементынапример, prnt_matrix
и т. д. *
Пример использования / вывода
$ ./bin/matrix_cr_obtn
enter number of rows: 5
enter number of cols: 3
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
Использование памяти / проверка ошибок
В любом написанном вами коде, который динамически распределяет память, у вас есть 2 обязанностей относительноЛюбой выделенный блок памяти: (1) всегда сохраняет указатель на начальный адрес для блока памяти, поэтому (2) он может быть освобожден , когда он больше не нужен.
Крайне важно, чтобы вы использовали программу проверки ошибок памяти, чтобы убедиться, что вы не пытаетесь получить доступ к памяти или писать за пределами / за пределами выделенного блока, пытаться прочитать или основать условный переход на неинициализированном значениии, наконец, подтвердить, что вы освобождаете всю выделенную память.
Для Linux valgrind
- нормальный выбор.Для каждой платформы есть похожие проверки памяти.Все они просты в использовании, просто запустите вашу программу через нее.
$ valgrind ./bin/matrix_cr_obtn
==10251== Memcheck, a memory error detector
==10251== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==10251== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==10251== Command: ./bin/matrix_cr_obtn
==10251==
enter number of rows: 5
enter number of cols: 3
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
==10251==
==10251== HEAP SUMMARY:
==10251== in use at exit: 0 bytes in 0 blocks
==10251== total heap usage: 6 allocs, 6 frees, 100 bytes allocated
==10251==
==10251== All heap blocks were freed -- no leaks are possible
==10251==
==10251== For counts of detected and suppressed errors, rerun with: -v
==10251== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Всегда подтверждайте, что вы освободили всю выделенную память и что ошибок памяти нет.
Посмотрите вещии дайте мне знать, если у вас есть дополнительные вопросы.