C не имеет null
, имеет NULL
. Итак, попробуйте это:
dict* NewDictionary(void) {
return calloc(sizeof(dict));
}
Это исправляет несколько проблем:
- Вы оставляли
value
и key
неинициализированными, чтобы они могли содержать случайный мусор. Использование calloc()
инициализирует все до 0, что в контексте указателя равно NULL
. Это даже не займет намного больше времени.
- Вы ничего не возвращали. Это неопределенное поведение. Если ваша функция заканчивается без оператора
return
, то только по счастливой случайности все будет возвращено.
- Вы использовали
dict_pair
вместо struct dict_pair
. В C ++ struct
имена находятся в пространстве имен обычного типа, то есть t x = { 0 };
является допустимым C ++, но в C вам нужно сказать struct t x = { 0 };
.
- Вы не проверяли возвращаемое значение
malloc()
(сейчас calloc()
, но применяются те же правила). Если памяти недостаточно, calloc()
возвращает NULL
. Я бы не хотел разыменовывать указатель NULL
в случае аварии. Нам не нужно проверять возвращаемое значение здесь, потому что я покончил со всеми промежуточными шагами - нам достаточно calloc()
1031 *
Обратите внимание, что calloc()
немного менее портативен. Хотя стандарт требует, чтобы void *p = 0
устанавливал указатель на нулевой указатель, он не требует, чтобы нулевой указатель был «все биты установлены в ноль», что технически делает calloc()
. Если вы не хотите использовать calloc()
по этой причине, вот версия, которая делает то же самое с malloc()
:
dict* NewDictionary(void) {
dict *dictionary = malloc(sizeof(dict));
if(dictionary) {
dictionary->head = NULL;
dictionary->tail = NULL;
dictionary->value = NULL;
dictionary->key = NULL;
}
return dictionary;
}
Или:
dict* NewDictionary(void) {
dict *dictionary = malloc(sizeof(dict));
if(dictionary == NULL) return NULL;
dictionary->head = NULL;
dictionary->tail = NULL;
dictionary->value = NULL;
dictionary->key = NULL;
return dictionary;
}
Посмотрите, насколько лучше версия calloc()
?
Что касается вашего второго вопроса:
Кроме того, могу ли я ссылаться рекурсивно объявлять ту же структуру внутри структуры?
Нет, вы не можете сделать это:
struct t {
struct t x;
}
Но вы можете сделать это (то, что вы делаете, и что вы хотите):
struct t {
struct t *x;
}
Вы можете иметь указатель на struct
внутри самого struct
, но вы не можете иметь фактический struct
внутри самого struct
. То, что вы делаете, совершенно законно, потому что вы используете указатели.