Добавить функцию для C с динамическим распределением памяти - PullRequest
1 голос
/ 14 апреля 2019

После этого вопроса я пытаюсь изменить код, указанный в этой записи блога , чтобы создать функцию append с использованием динамического распределения памяти. Это то, что я до сих пор:

#include <stdio.h>
#include <stdlib.h>

typedef struct intlist_ {
  int size;
  int* list;
} intlist;

void append(intlist* arr, int value){
  realloc((*arr).list, sizeof((*arr).list) + sizeof(int));
  (*arr).size = (*arr).size + 1;
  (*arr).list[(*arr).size -1] = value;
}

int main() {

  intlist arr;
  arr.size = 4;
  arr.list = malloc(arr.size * sizeof(int));

  arr.list[0] = 0;
  arr.list[1] = 5;
  arr.list[2] = 3;
  arr.list[3] = 64;

  append(&arr, 12);

  for (int ii = 0; ii < arr.size; ii++)
    printf("%d, ", arr.list[ii]);

  free(arr.list);
  return 0;
}

Однако полученный результат неверен:

clang версия 7.0.0-3 ~ ubuntu0.18.04.1 (tags / RELEASE_700 / final) main.c: 10: 3: предупреждение: игнорирование возвращаемого значения функции, объявленной с Атрибут «warn_unused_result» [-Wunused-result] realloc ((* arr) .list, sizeof ((* arr) .list) + sizeof (int)); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~ 1 предупреждение сгенерировано. 0, 5, 3, 64, 0, 5, 3, 64, 12,

Я использую этот онлайн-компилятор для тестирования, где вы также можете увидеть последние версии приведенного выше кода. Буду признателен, если вы поможете мне узнать, где моя ошибка и как я могу ее исправить. Заранее спасибо за вашу поддержку.

P.S. Вы можете получить окончательную версию кода здесь, в this Gist .

Ответы [ 2 ]

2 голосов
/ 15 апреля 2019

Закрыть, но:

  1. sizeof((*arr).list) не даст вам размер массива. Вместо этого он даст вам размер int*.
  2. realloc делает недействительным исходный указатель, и его дальнейшее использование является неопределенным поведением. Вместо этого используйте возвращаемое значение.

Поэтому измените строку realloc, чтобы вместо нее использовать сохраненный размер списка, и обновите указатель возвращаемым значением:

(*arr).list = realloc((*arr).list, ((*arr).size + 1) * sizeof(int));

Пара других советов:

  • ptr-> совпадает с (*ptr)., но легче для чтения. Я предлагаю изменить все ваши (*arr).size и (*arr).list на arr->size и arr->list.
  • realloc, как и его братья, не гарантируют успеха. Вы должны проверить возвращаемое значение для null, чтобы отловить ошибки.
  • Предупреждение о лязге (как это часто бывает) полезно - проверка возвращаемого значения позволила бы решить пару проблем.
1 голос
/ 15 апреля 2019
  • Неправильный размер.sizeof((*arr).list) - это размер указателя, а не int.

  • Возвращаемое значение не используется.realloc() возвращает новый указатель.

  • Нет NULL check

Вместо использования склонного к ошибке ptr = some_alloc(sizeof(type) * n), используйте ptr = some_alloc(sizeof *ptr * n)


void append(intlist *arr, int value){
  int *new_ptr = realloc(arr->list, sizeof *(arr->list) * (arr->size + 1u));
  if (new_ptr == NULL) {
    fprintf(stderr, "Out of memory\n");
    exit (EXIT_FAILURE);
  }
  arr->list = new_ptr;
  arr->list[arr->size] = value;
  arr->size++;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...