Как инициализировать структуру в соответствии со стандартами языка программирования C - PullRequest
414 голосов
/ 01 декабря 2008

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

typedef struct MY_TYPE {
  bool flag;
  short int value;
  double stuff;
} MY_TYPE;

void function(void) {
  MY_TYPE a;
  ...
  a = { true, 15, 0.123 }
}

Является ли это способом объявления и инициализации локальной переменной MY_TYPE в соответствии со стандартами языка программирования C (C89, C90, C99, C11 и т. Д.)? Или есть что-нибудь лучше или хотя бы работает?

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

Ответы [ 14 ]

669 голосов
/ 01 декабря 2008

В (ANSI) C99 вы можете использовать обозначенный инициализатор для инициализации структуры:

MY_TYPE a = { .flag = true, .value = 123, .stuff = 0.456 };

Редактировать: другие члены инициализируются как ноль: «пропущенные члены поля неявно инициализируются так же, как объекты, которые имеют статическую продолжительность хранения». (https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html)

180 голосов
/ 01 декабря 2008

Вы можете сделать это с помощью составного литерала . Согласно этой странице, он работает в C99 (который также считается ANSI C ).

MY_TYPE a;

a = (MY_TYPE) { .flag = true, .value = 123, .stuff = 0.456 };
...
a = (MY_TYPE) { .value = 234, .stuff = 1.234, .flag = false };

Обозначения в инициализаторах являются необязательными; Вы также можете написать:

a = (MY_TYPE) { true,  123, 0.456 };
...
a = (MY_TYPE) { false, 234, 1.234 };
85 голосов
/ 09 июня 2013

Я вижу, что вы уже получили ответ о ANSI C 99, поэтому я брошу кость о ANSI C 89. ANSI C 89 позволяет вам инициализировать структуру следующим образом:

typedef struct Item {
    int a;
    float b;
    char* name;
} Item;

int main(void) {
    Item item = { 5, 2.2, "George" };
    return 0;
}

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

Если вы не инициализируете значения в своей структуре, все переменные будут содержать «мусорные значения».

Удачи!

35 голосов
/ 01 декабря 2008

a = (MYTYPE){ true, 15, 0.123 };

будет хорошо в C99

18 голосов
/ 01 декабря 2008

Ты почти понял ...

MY_TYPE a = { true,15,0.123 };

Быстрый поиск по 'struct initialize c' показывает мне это

13 голосов
/ 08 июня 2016

Стандарт языка программирования C ИСО / МЭК 9899: 1999 (широко известный как C99) позволяет использовать обозначенный инициализатор для инициализации членов структуры или объединения следующим образом:

MY_TYPE a = { .stuff = 0.456, .flag = true, .value = 123 };

Он определен в paragraph 7, разделе 6.7.8 Initialization стандарта ИСО / МЭК 9899: 1999 как:

Если обозначение имеет форму
, Идентификатор
тогда текущий объект (определенный ниже) должен иметь структуру или тип объединения, а идентификатор должен быть именем члена этого типа.

Обратите внимание, что paragraph 9 того же раздела гласит:

За исключением случаев, когда явно указано иное, для целей настоящего подпункта неназванные члены объектов структуры и типа объединения не участвуют в инициализации. Безымянные члены объектов структуры имеют неопределенное значение даже после инициализации.

В реализации GNU GCC пропущенные члены инициализируются как нулевое или нулевое значение, соответствующее типу. Как указано в разделе 6.27 Назначенные инициализаторы документации GNU GCC:

Пропущенные члены поля неявно инициализируются так же, как объекты со статической продолжительностью хранения.

Компилятор Microsoft Visual C ++ должен поддерживать указанные инициализаторы начиная с версии 2013 согласно официальному сообщению в блоге План соответствия C ++ . В статье Initializing unions and structs из Инициализаторов в документации MSDN Visual Studio предполагается, что неназванные элементы инициализируются равными нулю соответствующими значениями, аналогично GNU GCC.

Стандарт ИСО / МЭК 9899: 2011 (широко известный как С11), который заменил ИСО / МЭК 9899: 1999, сохраняет обозначенные инициализаторы в разделе 6.7.9 Initialization. Он также сохраняет paragraph 9 без изменений.

Новый Стандарт ISO / IEC 9899: 2018 (широко известный как C18), который заменил ISO / IEC 9899: 2011, сохраняет назначенные инициализаторы в разделе 6.7.9 Initialization. Он также сохраняет paragraph 9 без изменений.

13 голосов
/ 04 сентября 2013

как сказал Рон Нуни:

typedef struct Item {
    int a;
    float b;
    char* name;
} Item;

int main(void) {
    Item item = {5, 2.2, "George"};
    return 0;
}

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

Если вы не инициализируете значения в своей структуре (т. Е. Если вы просто объявляете эту переменную), все variable.members будут содержать «мусорные значения», только если объявление локальное! * Если декларация глобальная или статическая (как в этом случае), все неинициализированные variable.members будут автоматически инициализированы следующим образом:

  • 0 для целых чисел и с плавающей точкой
  • '\0' для char (конечно, это то же самое, что 0, и char - целочисленный тип)
  • NULL для указателей.
4 голосов
/ 01 декабря 2008
void function(void) {
  MY_TYPE a;
  a.flag = true;
  a.value = 15;
  a.stuff = 0.123;
}
2 голосов
/ 04 декабря 2015

Я нашел другой способ инициализации структур.

Структура:

typedef struct test {
    int num;
    char* str;
} test;

Инициализация:

test tt = {
    num: 42,
    str: "nice"
};

Согласно документации GCC, этот синтаксис является устаревшим, поскольку GCC 2.5 .

2 голосов
/ 20 апреля 2014

Если MS не обновилась до C99, MY_TYPE a = {true, 15,0.123};

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...