Использование realloc путем умножения целого числа указателя и sizeof (int) не работает - PullRequest
0 голосов
/ 13 июня 2018

Код:

void main() {
    int *array = calloc(5, sizeof(int));
    int *amount = 9;
    array[0] = 1;
    array[1] = 2;
    array[3] = 5;

    int i = 0;
    while (i < 5) {
        printf("%d ", array[i]);
        i += 1;
    }

    printf("%d", amount); //Printing
    array = realloc(array, amount * sizeof(int)); //Problem is here
    printf("\n");
    i = 0;
    while (i < 9) {
        printf("%d ", array[i]);
        i += 1;
    }
    free(array);
}

Там написано «недопустимые операнды в двоичном * (имеют« int * »и« unsigned int »), но когда я попытался напечатать« количество », на самом деле это 9? I»я пытаюсь использовать целочисленный указатель, чтобы я мог передать его по ссылке.

Ответы [ 4 ]

0 голосов
/ 13 июня 2018

Пара вещей:

Во-первых,

int *amount = 9;

не делает то же самое, что

*amount = 9;

В первом случае, *только там, чтобы указать, что amount имеет тип указателя, и мы инициализируем значение pointer (т. е. адрес) в 9, который, скорее всего, не является допустимым значением указателя, и пытаемсяразыменование может привести к ошибке во время выполнения.

Во втором случае мы присваиваем целочисленное значение 9 объекту, на который указывает amount.

Почему это не сломалось, когда вы передали amount в printf?По сути, вы вызывали неопределенное поведение, передавая аргумент неправильного типа (%d ожидает int, вы передали int *).Одним из возможных результатов неопределенного поведения является получение ожидаемого результата.По какой-то причине printf смог обработать это значение int * как int.Большинство компиляторов должны отмечать это несоответствие типов, но вам может понадобиться проверить уровень предупреждения, чтобы увидеть его.

Существует ограничение на двоичный оператор *, согласно которому оба операнда имеют арифметический тип.int * не является арифметическим типом, следовательно, является диагностическим.

Исходя из того, как вы на самом деле используете amount в своем коде, вы должны были объявить его не как указатель, а как обычный int:

int amount = 9;

Во-вторых, как правило, вы не хотите присваивать результат realloc исходному указателю.Если realloc завершится неудачно, он вернет NULL и оставит исходный блок памяти как есть.Однако, если вы вернете этот NULL к исходному указателю, вы потеряете доступ к этой памяти.Рекомендуется присваивать результат realloc временному объекту, а затем убедиться, что временный объект действителен, прежде чем присвоить его обратно оригиналу:

int *tmp = realloc( array, amount * sizeof *array );
if ( tmp )
{
  array = tmp;
}
else
{
  // handle realloc error
}

Обратите внимание на использование sizeof *array вместо sizeof (int).sizeof является оператором, подобным унарному * или унарному +, и его операндом может быть имя типа в скобках или выражение. выражение *array имеет тип int, поэтому sizeof *array == sizeof (int).Это помогает немного облегчить чтение кода, и если вы когда-нибудь измените тип array (скажем, double *), вам не придется обновлять вызов realloc.Это также очень полезно при распределении типов многомерных массивов - вы бы предпочли написать

int (*arr)[10] = malloc( sizeof (int) * 10 * rows);

или

int (*arr)[10] = malloc( sizeof *arr * rows );

?

0 голосов
/ 13 июня 2018

amount имеет тип int *.Причина, по которой printf печатает 9, не в том, что amount указывает на значение 9, а в том, что значение 9 приведено к указателю.

Теперь в вашем выражении array = realloc(array, amount * sizeof(int));.Вы пытаетесь умножить указатель (а не значение, на которое указывает amount).Спросите себя, какой должна быть семантика этого.Вместо int *amount = 9; вы, вероятно, хотите

int *amount = calloc(1, sizeof(int));
*amount = 9;

, который объявляет указатель и выделяет место для одного целого числа, а вместо array = realloc(array, amount * sizeof(int)); вы, вероятно, хотите

array = realloc(array, *amount * sizeof(int));

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

0 голосов
/ 13 июня 2018

amount должен быть определен как int, а не int *.

int amount = 9;
0 голосов
/ 13 июня 2018

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

int *amount = 9;      // only use that for memory mapped hardware registers
printf("%d", amount); //re-interpreting the pointer value as an int
array = realloc(array, amount * sizeof(int));   // hopefully you got a diagnostic

ужасно.Указатель должен быть только нулевым указателем точки на действительный объект.Полная остановка.Арифметика указателей имеет смысл только внутри массива.

Если переменная должна содержать целочисленные значения, то она должна иметь целочисленный тип:

int amount = 9;
printf("%d", amount); //Printing
array = realloc(array, amount * sizeof(int)); //Problem is here

Если вам нужен указатель напросто объявите его и используйте в качестве указателя :

int amount = 9;
int *p_amount = &amount;
printf("%d - %d\n", amount, *p_amount); //Printing
array = realloc(array, (*p_amount) * sizeof(int)); //No problem now
...