Jak zainicjować strukturę zgodnie ze standardami języka programowania C

Chcę zainicjalizować element struct, podzielony na deklarację i inicjalizację. To jest to co mam:

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

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

Jest to sposób deklarowania i inicjalizacji lokalnej zmiennej MY_TYPE zgodnie ze standardami języka programowania C (C89, C90, C99, C11, itd.)? A może jest coś lepszego albo przynajmniej działa?

Update skończyło się na statycznym elemencie inicjalizacyjnym, w którym ustawiałem każdy podelement zgodnie z moimi potrzebami.

Author: PF4Public, 2008-12-01

13 answers

W (ANSI) C99, możesz użyć wyznaczonego inicjalizatora do zainicjalizowania struktury:

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

Edit: inne elementy składowe są inicjalizowane jako zero: "pominięte elementy pól są inicjowane domyślnie tak samo jak obiekty, które mają statyczny czas przechowywania."( https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html )

 613
Author: philant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-07 08:43:02

Możesz to zrobić za pomocą złożonego literału . Zgodnie z tą stroną, działa w C99 (który również liczy się jako 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 };

Oznaczenia w inicjalizatorach są opcjonalne; można też napisać:

a = (MY_TYPE) { true,  123, 0.456 };
...
a = (MY_TYPE) { false, 234, 1.234 };
 166
Author: CesarB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-08 08:00:40

Widzę, że otrzymałeś już odpowiedź o ANSI C 99, więc rzucę kość o ANSI C 89. ANSI C 89 pozwala na inicjalizację struktury w ten sposób:

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

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

Należy pamiętać, że w momencie inicjalizacji nawet jednego obiektu/ zmiennej w strukturze wszystkie pozostałe zmienne zostaną zainicjalizowane do wartości domyślnej.

Jeśli nie zainicjalizujesz wartości w swojej strukturze, wszystkie zmienne będą zawierać "wartości śmieci".

Powodzenia!
 82
Author: Ron Nuni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-05 11:10:24

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

Dobrze by było w C99]}
 35
Author: qrdl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-01 13:27:22

Prawie to masz...

MY_TYPE a = { true,15,0.123 };

Szybkie wyszukiwanie na 'struct initialize c' pokazuje mi to

 17
Author: Kieveli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-01 13:21:54

Jak powiedział Ron Nuni:

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

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

Ważna rzecz do zapamiętania: w momencie inicjalizacji nawet jednego obiektu/zmiennej w strukturze, wszystkie pozostałe jej zmienne zostaną zainicjalizowane do wartości domyślnej.

Jeśli nie zainicjalizujesz wartości w swojej strukturze (tzn. jeśli tylko zadeklarujesz tę zmienną), wszystkie variable.members będą zawierać "wartości śmieci", tylko jeśli deklaracja jest lokalna!

Jeśli deklaracja jest globalna lub statyczna (jak w tym przypadku), wszystkie niewtajemniczeni variable.members zostanie zainicjowany automatycznie do:

  • 0 dla liczb całkowitych i zmiennoprzecinkowych
  • '\0' dla char (oczywiście jest to dokładnie to samo co 0, a char jest typem całkowitym)
  • NULL dla wskaźników.
 12
Author: r_goyal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-26 05:56:09

C standard języka programowania ISO/IEC 9899: 1999 (powszechnie znany jako C99) pozwala na użycie wyznaczonego inicjalizatora do inicjalizacji członków struktury lub Unii w następujący sposób:

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

Jest zdefiniowany w paragraph 7, Sekcja 6.7.8 Initialization normy ISO/IEC 9899:1999 jako:

Jeśli wyznacznik ma postać
. identyfikator
wtedy bieżący obiekt (zdefiniowany poniżej) ma strukturę lub typ związku, a identyfikatorem jest nazwa członka ten typ.

Zauważ, że paragraph 9 tej samej sekcji stwierdza, że:

O ile wyraźnie nie zaznaczono inaczej, do celów tej podklasy nienazwane elementy obiektów struktury i typu Unii nie uczestniczą w inicjalizacji. nienazwane elementy struktury mają nieokreśloną wartość nawet po inicjalizacji.

W implementacji GNU GCC pominięte elementy są inicjalizowane jako zero lub zero-podobne do wartości typowej. Jak podano w sekcji 6.27 wyznaczone Inicjalizatory dokumentacji GNU GCC:

Pominięte elementy pól są domyślnie inicjowane tak samo jak obiekty, które mają statyczny czas przechowywania.

Kompilator Microsoft Visual C++ powinien obsługiwać wyznaczone inicjalizatory od wersji 2013 zgodnie z oficjalnym postem na blogu C++ conform Roadmap. Paragraf Initializing unions and structs z Inicjalizatorów artykuł w dokumentacji MSDN Visual Studio sugeruje, że nienazwani członkowie inicjalizowani do odpowiednich wartości podobnych do zera, podobnie jak GNU GCC.

Nowa norma ISO/IEC 9899: 2011 (powszechnie znana jako C11), która zastąpiła ISO / IEC 9899: 1999, zachowuje wyznaczone inicjalizatory w sekcji 6.7.9 Initialization. Zachowuje również paragraph 9 bez zmian.

 11
Author: PF4Public,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-08 11:43:11
void function(void) {
  MY_TYPE a;
  a.flag = true;
  a.value = 15;
  a.stuff = 0.123;
}
 4
Author: robert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-19 13:37:10

Jeśli MS nie zaktualizował do C99, MY_TYPE a = {true, 15, 0.123};

 2
Author: eddyq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-20 19:39:46

Znalazłem inny sposób inicjalizacji struktur.

Struktura:

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

Inicjalizacja:

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

Zgodnie z dokumentacją GCC, składnia ta jest przestarzała od GCC 2.5.

 2
Author: MichaelWang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-05 11:30:39

Nie spodobała mi się żadna z tych odpowiedzi, więc zrobiłam swoje. Nie wiem czy to jest ANSI C czy nie, to tylko GCC 4.2.1 w trybie domyślnym. Nigdy nie pamiętam bracketingu, więc zaczynam od podzbioru moich danych i walczę z komunikatami o błędach kompilatora, dopóki się nie wyłączy. Czytelność jest moim priorytetem.

    // 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"}
    };

Dane mogą rozpocząć życie jako plik rozdzielany tabulatorami, który przeszukiwasz-zamieniasz na coś innego. Tak, to Debian. Więc jedna zewnętrzna para {} (wskazując tablicę), następnie kolejna para dla każdej struktury wewnątrz. Z przecinkami pomiędzy. Umieszczanie rzeczy w nagłówku nie jest bezwzględnie konieczne, ale mam około 50 elementów w mojej strukturze, więc chcę je w osobnym pliku, ZARÓWNO aby utrzymać bałagan z mojego kodu, a więc łatwiej jest go zastąpić.

 1
Author: Alan Corey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-13 02:46:44

Struktura w C może być zadeklarowana i zainicjalizowana w następujący sposób:

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;
}
 0
Author: Ajay Parashar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-26 14:55:37

Czytałem dokumentację Microsoft Visual Studio 2015 Do inicjalizacji typów agregatów jednak wszystkie formy inicjalizacji za pomocą {...} są tam wyjaśnione, ale inicjalizacja za pomocą kropki, o nazwie "designator" nie jest tam wymieniona. To też nie działa.

Inicjalizacja w standardzie C99 w rozdziale 6.7.8 wyjaśnia możliwości desygnatorów, ale moim zdaniem nie jest to jasne dla złożonych struktur. C99 standard w formacie pdf .

W moim umyśle, może be better to

  1. użyj inicjalizacji = {0}; dla wszystkich danych statycznych. Jest to mniej wysiłku dla kodu maszynowego.
  2. Użyj makr do inicjalizacji, na przykład

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

Makro można dostosować, jego lista argumentów może być niezależna od zmienionej zawartości struktury. Jest właściwe, jeśli mniej elementów powinno być inicjowane. Jest to również właściwe dla zagnieżdżonej struktury. 3. Prosta forma to: Inicjalizacja w podprogramie:

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

Ta rutyna wygląda jak Obiekt w C. Użyj thiz, a nie this, Aby skompilować go również z C++!

MyStruct data = {0}; //all is zero!
init_MyStruct(&data, 3, 456);
 0
Author: Hartmut Schorrig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-12 14:10:33