Как инициализировать структуру в соответствии со стандартами языка программирования 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
Ответ 5
Вы почти получили его...
MY_TYPE a = { true,15,0.123 };
Быстрый поиск по 'struct initialize c' показывает мне это
Ответ 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.
На мой взгляд, может быть лучше
- Используйте
= {0};
-initialization для всех статических данных. Это меньше усилий для машинного кода. -
Использовать макросы для инициализации, например
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 */