Если тип возвращаемого значения функции void (вы не возвращаете новый pojnter в динамически распределенный массив), тогда вам нужно передать указатель на функцию по ссылке
void changeNumber(int **grades, int size);
В противном случае функция будет иметь дело с копией исходного аргумента и изменения копии не влияют на исходный аргумент.
Но так как функция устанавливает новый размер массива, то пользователь функции должен знать, что это новый размер массива. Так что вы должны, например, вернуть из функции новый размер массива.
int changeNumber(int **grades, int size);
Также, если новый выделенный массив имеет размер, который меньше текущего размера, тогда нет необходимости копировать элементы в сами
newGrades = (int*)malloc(newSize * sizeof(int));
for (i = 0; i < (newSize-1); i++)
{
grades[i] = grades[i];
}
И вам нужно присвоить новый указатель старому указателю на первый элемент массива.
Вместо типа int, используемого для размера массива, он является гораздо лучше использовать целое число без знака size_t
.
Функция может выглядеть, например, следующим образом
size_t changeNumber( int **grades, size_t size )
{
size_t newSize = 0;
printf( "Enter new number of grades: " );
if ( scanf( "%zu", &newSize ) == 1 && size != newSize )
{
int *newGrades = realloc( *grades, newSize * sizeof( int ) );
if ( newGrades != NULL )
{
if ( size < newSize )
{
for ( size_t i = size; i < newSize; i++ )
{
printf( "Enter grade %zu: ", i + 1 );
scanf("%d", newGrades + i );
newGrades[i] = checkNumber( newGrades[i] );
}
}
size = newSize;
*grades = newGrades;
}
}
for ( size_t i = 0; i < size; i++ )
{
printf( "%d ", ( *grades )[i] );
}
putchar( '\n' );
return size;
}
Обратите внимание на тот указатель, который косвенно передается в функцию через указатель на него в качестве аргумента также должен указывать на динамически размещаемый массив.