Передача указателя на указатель для перераспределения в функции - PullRequest
0 голосов
/ 04 июня 2019

Я начинающий программист на C и имею проблемы с реализацией (упорядоченного) динамического массива структур. Перед добавлением элемента в массив я хочу проверить, заполнен ли он, и удвоить его размер в этом случае:

void insert_translation(dict_entry **dict, char *word, char *translation){
    if( dictionary_entries == dictionary_size ){
        dict_entry *temp_dict;
        temp_dict = realloc(&dict, (dictionary_size *= 2) * sizeof(dict_entry) );
        // printf("Increased dict size to %d\n", dictionary_size);
        // if(temp_dict == NULL){
        //     fprintf(stderr, "Out of memory during realloc()!\n");
        //     /*free(dict);
        //     exit(EXIT_OUT_OF_MEMORY);*/
        // }

        //free(dict);
        //*dict = temp_dict;
    }

    dictionary_entries++;
    printf("Inserted %s into dict - %d of %d filled.\n", word, dictionary_entries, dictionary_size);
}

Я вызываю функцию из основной функции следующим образом:

dictionary_size = 2; //number of initial key-value pairs (translations)
dictionary_entries = 0;
dict_entry *dictionary = malloc(dictionary_size * sizeof(dict_entry));
[...]
insert_translation(&dictionary, "bla", "blub");

В моем понимании словарь - это указатель на пробел в памяти. & словарь - это указатель на указатель, который я передаю функции. В функции dict указывается указатель на указатель, поэтому & dict должен быть указателем на область в памяти? Однако, когда я пытаюсь скомпилировать, я получаю следующее сообщение об ошибке:

pointer being realloc'd was not allocated

Редактировать

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

Ответы [ 2 ]

2 голосов
/ 04 июня 2019

Проблема в этом операторе

temp_dict = realloc(&dict, (dictionary_size *= 2) * sizeof(dict_entry) );

Параметр dict имеет тип

dict_entry **dict

в операторе, который перераспределяет память, которую вы должны использовать для значенияуказатель *dic но вы используете выражение &dict, которое имеет тип dict_entry ***.

Сравните тип левой части присваивания

ict_entry *temp_dict

с типомперераспределенный указатель.Они должны быть одинаковыми (за исключением того, что в C один из них может иметь тип void *)

Поэтому необходимо написать

temp_dict = realloc(*dict, (dictionary_size *= 2) * sizeof(dict_entry) );
                    ^^^^^

В Си аргументы передаются по значению.Если вы хотите изменить исходное значение аргумента, вы должны передать его по ссылке через указатель на аргумент.В функции необходимо разыменовать указатель, чтобы изменить объект, на который указывает указатель.

1 голос
/ 04 июня 2019

&dict -> *dict.Вы можете упростить код, используя тип возврата, чтобы избежать таких ошибок:

dict_entry* insert_translation(dict_entry* dict, char *word, char *translation)
{
  ...

  if( dictionary_entries == dictionary_size )
  {
    dictionary_size *= 2;

    dict_entry *tmp = realloc(dict, sizeof(dict_entry[dictionary_size]));
    if(tmp == NULL)
    {
      // error handling, free(dict) etc
    }
    else
    {
      dict = tmp;
    }
  }

  ...

  return dict;
}
...