Продолжая мои комментарии - если вы объявите int *p
; и ваш прототип - void scanEntries(int total, int *p)
, вы просто называете его как scanEntries(initSize, p);
(здесь нет '*'
) "warning: passing argument 2 of ‘scanEntries’ makes pointer from integer without a cast [enabled by default]"
из-за вашей попытки передать *p
, который разыменовывает целочисленный указатель 'p'
, что приводит к int
значение вместо указателя на int .
Помимо вашей первоначальной проблемы с передачей указателя, у вас есть большое количество дополнительных ошибок:
В main()
вам не следует звонить enterSize()
во второй раз, вместо этого:
scanEntries (initSize, p);
Кроме того, вы должны проверить КАЖДОЕ распределение и КАЖДЫЙ ввод, например,
p = calloc(initSize, sizeof(int));
if (!p) { /* VALIDATE EVERY ALLOCATION */
perror ("calloc-p");
return 1;
}
и, наконец, если вы выделите память, выработаете хорошие привычки и обеспечите ее free
, когда она больше не нужна, например,
free (p); /* don't forget to free what you allocate */
}
В scanInt()
необходимо указать указатель от output
до scanf
, например,
if (scanf ("%d", &output) != 1) { /* VALIDATE EVERY INPUT */
fputs ("error: invalid input - not an integer.\n", stderr);
exit (EXIT_FAILURE);
}
( примечание: &output
в scanf
вызове)
Кроме того, хотя и эквивалентно, не используйте обозначение указателя для *(p + number)
, вместо этого просто используйте p[number]
, оно более читабельно.
Если сложить все вместе, вы можете сделать:
#include <stdio.h>
#include <stdlib.h>
/* function to scan any integer value */
int scanInt (void)
{
int output;
if (scanf ("%d", &output) != 1) { /* VALIDATE EVERY INPUT */
fputs ("error: invalid input - not an integer.\n", stderr);
exit (EXIT_FAILURE);
}
return (output);
}
/* scanInt but as one entry out of a group */
int scanEntry (int number, int total)
{
printf ("Please enter score %d of %d: ", number+1, total);
return (scanInt());
}
/* scanEntry for an entire dynamic array) */
void scanEntries (int total, int *p)
{
int number;
for (number = 0; number < total; number++) {
p[number] = scanEntry (number, total);
#ifdef TESTING
printf (" scanEntries testing - %d\n", p[number]);
#endif
}
}
/* scanInt but with a prompt to enter size */
int enterSize (void)
{
printf ("Please enter size of array: ");
return (scanInt());
}
int main (void) {
/* entering initial size, done in a separate function */
int initSize = enterSize(),
*p; /* p is an int pointer */
p = calloc(initSize, sizeof(int));
if (!p) { /* VALIDATE EVERY ALLOCATION */
perror ("calloc-p");
return 1;
}
printf ("%d\n", initSize);
scanEntries (initSize, p);
printf ("%d entries read:\n\n", initSize);
for (int i = 0; i < initSize; i++)
printf ("p[%2d] : %d\n", i, p[i]);
free (p); /* don't forget to free what you allocate */
}
Пример использования / Вывод
( примечание: вы можете добавить -DTESTING
к опциям вашего компилятора, чтобы определить TESTING
для активации дополнительного кода.)
$ ./bin/scanentries
Please enter size of array: 4
4
Please enter score 1 of 4: 1
Please enter score 2 of 4: 2
Please enter score 3 of 4: 3
Please enter score 4 of 4: 4
4 entries read:
p[ 0] : 1
p[ 1] : 2
p[ 2] : 3
p[ 3] : 4
Использование памяти / проверка ошибок
В любом написанном вами коде, который динамически распределяет память, у вас есть 2 обязанностей относительно любого выделенного блока памяти: (1) всегда сохраняйте указатель на начальный адрес для блока памяти, так что, (2) он может быть освобожден , когда он больше не нужен.
Крайне важно, чтобы вы использовали программу проверки ошибок памяти, чтобы гарантировать, что вы не пытаетесь получить доступ к памяти или писать за пределами / за пределами выделенного блока, пытаться прочитать или основать условный переход на неинициализированном значении и, наконец, , чтобы подтвердить, что вы освобождаете всю выделенную память.
Для Linux valgrind
- нормальный выбор. Для каждой платформы есть похожие проверки памяти. Все они просты в использовании, просто запустите вашу программу через него.
$ valgrind ./bin/scanentries
==11795== Memcheck, a memory error detector
==11795== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==11795== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==11795== Command: ./bin/scanentries
==11795==
Please enter size of array: 4
4
Please enter score 1 of 4: 1
Please enter score 2 of 4: 2
Please enter score 3 of 4: 3
Please enter score 4 of 4: 4
4 entries read:
p[ 0] : 1
p[ 1] : 2
p[ 2] : 3
p[ 3] : 4
==11795==
==11795== HEAP SUMMARY:
==11795== in use at exit: 0 bytes in 0 blocks
==11795== total heap usage: 1 allocs, 1 frees, 16 bytes allocated
==11795==
==11795== All heap blocks were freed -- no leaks are possible
==11795==
==11795== For counts of detected and suppressed errors, rerun with: -v
==11795== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Всегда подтверждайте, что вы освободили всю выделенную память и что ошибок памяти нет.
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.