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

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

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 и т.д.)? Или есть что-нибудь лучше или хотя бы работает?

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

Ответ 1

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

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

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

Ответ 2

Вы можете сделать это с помощью составного литерала. Согласно этой странице, он работает на 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 };

Ответ 3

Я вижу, что вы уже получили ответ о 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;
}

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

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

Удачи!

Ответ 4

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

будет отлично работать на C99

Ответ 6

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

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 для указателей.

Ответ 7

Стандарт языка программирования

C ISO/IEC 9899: 1999 (обычно известный как C99) позволяет использовать инициализатор назначенный для инициализации членов структуры или объединения следующим образом

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

В разделе paragraph 7, раздел 6.7.8 Initialization стандарта ISO/IEC 9899: 1999 определено:

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

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

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

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

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

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

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

Ответ 8

void function(void) {
  MY_TYPE a;
  a.flag = true;
  a.value = 15;
  a.stuff = 0.123;
}

Ответ 9

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

Ответ 10

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

Структура:

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

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

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

В соответствии с документацией GCC этот синтаксис устарел после GCC 2.5.

Ответ 11

Мне не понравился ни один из этих ответов, поэтому я сделал свой собственный. Я не знаю, является ли это ANSI C или нет, это просто GCC 4.2.1 в нем по умолчанию. Я никогда не помню брекетинг, поэтому я начинаю с подмножества моих данных и сражаюсь с сообщениями об ошибках компилятора, пока он не закроется. Чтение - это мой первый приоритет.

    // in a header:
    typedef unsigned char uchar;

    struct fields {
      uchar num;
      uchar lbl[35];
    };

    // in an actual c file (I have 2 in this case)
    struct fields labels[] = {
      {0,"Package"},
      {1,"Version"},
      {2,"Apport"},
      {3,"Architecture"},
      {4,"Bugs"},
      {5,"Description-md5"},
      {6,"Essential"},
      {7,"Filename"},
      {8,"Ghc-Package"},
      {9,"Gstreamer-Version"},
      {10,"Homepage"},
      {11,"Installed-Size"},
      {12,"MD5sum"},
      {13,"Maintainer"},
      {14,"Modaliases"},
      {15,"Multi-Arch"},
      {16,"Npp-Description"},
      {17,"Npp-File"},
      {18,"Npp-Name"},
      {19,"Origin"}
    };

Данные могут начать жизнь в виде файла с разделителями табуляции, который вы заменяете, чтобы массажировать в нечто другое. Да, это материал Debian. Итак, одна внешняя пара {} (указывающая массив), затем другая пара для каждой структуры внутри. С запятыми между. Помещение вещей в заголовок не является строго необходимым, но у меня есть около 50 элементов в моей структуре, поэтому я хочу их в отдельном файле, чтобы сохранить беспорядок из моего кода, и поэтому его легче заменить.

Ответ 12

Структура в C может быть объявлена ​​и инициализирована следующим образом:

typedef struct book
{
    char title[10];
    char author[10];
    float price;
} book;

int main() {
    book b1={"DS", "Ajay", 250.0};

    printf("%s \t %s \t %f", b1.title, b1.author, b1.price);

    return 0;
}

Ответ 13

Я прочитал документацию Microsoft Visual Studio 2015 для инициализации совокупных типов, но все формы инициализации с помощью {...} объясняются там, но здесь не упоминается инициализация с точкой с названием "обозначение". Это тоже не работает.

Стандартная глава C99 6.7.8 Инициализация объясняет возможность указателей, но, на мой взгляд, для сложных структур не совсем понятно. Стандарт C99 в формате pdf.

На мой взгляд, может быть лучше

  1. Используйте = {0}; -initialization для всех статических данных. Это меньше усилий для машинного кода.
  2. Использовать макросы для инициализации, например

    typedef MyStruct_t{ int x, int a, int b; } MyStruct; define INIT_MyStruct(A,B) { 0, A, B}

Макрос может быть адаптирован, его список аргументов может быть независимым от измененного содержимого структуры. Правильно, если нужно инициализировать меньшее количество элементов. Он также подходит для вложенной структуры. 3. Простая форма: Инициализация в подпрограмме:

void init_MyStruct(MyStruct* thiz, int a, int b) {
  thiz->a = a; thiz->b = b; }

Эта процедура выглядит как ObjectOriented в C. Используйте thiz, а не this чтобы скомпилировать ее с C++!

MyStruct data = {0}; //all is zero!
init_MyStruct(&data, 3, 456);

Ответ 14

Я искал хороший способ инициализации моей структуры, и я должен использовать ниже (C99). Это позволяет мне инициализировать одну структуру или массив структур так же, как обычные типы.

typedef struct {
    char *str;
    size_t len;
    jsmntok_t *tok;
    int tsz;
} jsmn_ts;

#define jsmn_ts_default (jsmn_ts){NULL, 0, NULL, 0}

Это можно использовать в коде как:

jsmn_ts mydata = jsmn_ts_default; /* initialization of a single struct */

jsmn_ts myarray[10] = {jsmn_ts_default, jsmn_ts_default}; /* initialization of
                                                    first 2 structs in the array */