2017-01-16 4 views
-1

Это моя структура:Инициализация динамического массива структур

typedef struct ElementToInsert { 
    char *key; 
    char *value; 
} element; 

Это моя функция:

void init_hash(int size, element**arr) { 
    *arr = malloc(size * sizeof(element*)); 
    if (arr == NULL) 
    { 
     printf("Out of memory\n"); 
     return 0; 
    } 
    for (int i = 0; i < size; i++) { 

     (*arr)[i].key = NULL; 
     (*arr)[i].value = NULL; 
    } 

} 

И main():

void main() { 
    element *hash_table = NULL; 
    int hash_table_size = 10; 
    init_hash(hash_table_size, &hash_table); 
} 

Проблема заключается в том, что, когда я запустите отладчик (в visual studio 2015) он не покажет мне все значения массива. Я ожидал увидеть что-то вроде: hash_table[0] = {key = NULL, value = NULL}, hash_table[1] = {key = NULL, value = NULL}, но я вижу это:

enter image description here

+1

Ваш код не имеет смысла. '* arr' является указателем на' element', поэтому вы должны выделить 'size * sizeof (element)' для него (то есть * размер * элементы, а не * размер * указатели). – melpomene

+0

'* arr' - это то же самое, что и' arr [0] '. Ваша первая итерация цикла перезаписывает указатель, который вы получили от первоначального вызова 'malloc'. – melpomene

+0

'main' должен возвращать' int', а не 'void'. – melpomene

ответ

0

Передача двойной указатель на init_hash является излишне сложным. Хотя существует много действительных применений для двойных указателей, это не один из них. Обычно двойные указатели используются для нескольких выходных переменных или для замены существующей памяти, но поскольку у вас нет возвращаемого значения, и вы все равно выделяете память, оно просто вызывает ошибки. Держите вещи простыми и верните указатель на свой список элементов.

element *init_hash(size_t size) { 
    element *hash = calloc(size, sizeof(element)); 

    if (hash == NULL) { 
     fprintf(stderr, "Out of memory\n"); 
     exit(1); 
    } 

    return hash; 
} 

Несколько примечаний. Во-первых, чтобы выделить массив структур, вы выделяете size * sizeof(element). Это выделяет память для size структур. Если вы используете size * sizeof(element*), который выделяет память для sizeУказатели на структуру. Оба действительны, но вы должны выбрать, с кем работаете. Кажется, вы работаете со списком структур.

В отличие от malloc, calloc будет нулевать память для вас. Это позволяет избежать необходимости вручную нуля каждой структуры, сохраняющей некоторый код и время.

Если у вас закончилась нехватка памяти, и у вас нет плана по ее устранению, вероятно, лучше всего сэкономить массу последующих сообщений об ошибках и exit.

И, наконец, размеры лучше всего хранить как size_t. Это тип, который C использует для размеров массива, и он может поймать некоторые проблемы с типом.

+2

примечание: Zero и NULL могут отличаться. – BLUEPIXY

+2

@BLUEPIXY Вы технически верны, лучший из правильных! Поскольку мы являемся техническими, '0' (константа) и' NULL' должны быть одинаковыми (см. 6.3.2.3.3). :) Но я знаю, что вы имеете в виду. 7.20.3.1 отмечает, что обнуление, выполняемое calloc «*, не обязательно должно быть таким же, как представление нуля с плавающей точкой или константы нулевой указатель *», но [это не было проблемой в течение десятилетий] (http: // c- faq.com/null/machexamp.html). Я бы сказал, используя эту технику, и если вы действительно обеспокоены, добавьте символ char ** null_check = calloc (1, sizeof (char *)); assert (NULL == null_check [0]); 'к вашим заголовкам. – Schwern

Смежные вопросы