Как инициализировать структуры C со значениями по умолчанию

У меня есть определенная структура:

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

typedef struct Node {
    int data;
    struct Node* prev;
    struct Node* next;
} Node;

typedef struct List {
    int size = 0;
    Node* head = NULL;
    Node* tai = NULL;
} List;

List* list1;

Для node все в порядке, но для List у меня ошибка объявления в Visual Studio (2022), я новичок в C, как объявить значения по умолчанию в структурах C?

В C нет значений по умолчанию для типов. Вы должны инициализировать переменные при их определении. (например, List list = {.size=0, .head=NULL, .tail=NULL};.) Для вашего указателя вам все равно сначала нужно выделить память.

Gerhardh 13.02.2023 12:38

Почему в этом случае лучше использовать указатель?

user21078706 13.02.2023 12:41

Кто сказал, что лучше использовать указатели? Вы используете указатели, если вам нужны указатели. Простая история. Обе ваши структуры используют указатели, кстати. Ваш пример содержит указатель List*list1;, который не указывает ни на какую допустимую память. Вы не можете назначить значения по умолчанию, не владея памятью.

Gerhardh 13.02.2023 12:44
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
134
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

В C, в отличие от C++, вы не можете инициализировать элементы данных в объявлениях структур, как вы это делаете.

typedef struct List {
    int size = 0;
    Node* head = NULL;
    Node* tai = NULL;
} List;

Также нет смысла объявлять глобальный указатель list1.

List* list1;

Что вам нужно, так это написать

typedef struct List {
    int size;
    Node* head;
    Node* tail; // I think you mean `tail` instead of `tai`
} List;

int main( void )
{
    List list1 = { .size = 0, .head = NULL, .tail = NULL };
    //...;
Ответ принят как подходящий

В C, инициализируется объект или нет, зависит от того, как вы объявляете объект, например, объявляете ли вы его как объект статической продолжительности хранения (который инициализируется нулем, если вы явно не инициализируете его чем-то другим) или объект автоматической длительности хранения (который не инициализируется, если вы не инициализируете его явно).

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

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

void init_list( List *p )
{
    p->size = 0;
    p->head = NULL;
    p->tail = NULL;
}

Предполагая, что объект объявлен внутри функции (не в области действия файла), вы можете использовать следующий код для объявления и инициализации объекта значениями по умолчанию:

List list1;
init_list( &list1 );

Если объект объявлен в области файла, вы не можете вызвать функцию init_list в области файла, но вы можете, например, вызвать функцию внутри функции main.

В качестве альтернативы, когда вы объявляете объект, вы также можете инициализировать отдельные члены:

List list1 = { 0, NULL, NULL };

Это также будет работать в области файлов.

Поскольку все инициализируется нулем, достаточно написать следующее:

List list1 = { 0 };

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

В C вы не можете определить struct со значениями по умолчанию для членов.

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

Пример:

typedef struct List {
    int size;
    Node* head;
    Node* tail;
} List;

// The init-value to use
const List List_INIT = {.size = 0, .head = NULL, .tail = NULL};

int main() {
    List l = List_INIT; // using the init-value
}
typedef struct List {
    int size;
    Node* head;
    Node* tail;
} List;

Здесь вы определили новый тип данных, вы не объявляли никаких переменных такого типа. Имя List не является переменной, это имя типа структуры. Имена size, head и tail не являются переменными, они являются идентификаторами членов этого struct.

Как объявить значения по умолчанию в структурах C?

Вы не можете определить тип со значением по умолчанию для членов. Просто укажите для него определение с/после объявления:

List apple;
memset (&apple, 0x00, sizeof apple);

/* Or */

List apple = { .size = 0, .head = NULL, .tail = NULL };

/* Or */

List apple = { .size = 0, .head = 0, .tail = 0 };

/* Or */ 

List mango = { 0, NULL, NULL };

/* Or */

List banana = { 0, 0, 0};

/* Or */

List orange = { 0 };¹

[1] — §6.7.9 Инициализация:

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

Другие вопросы по теме