So initialisieren Sie eine Struktur gemäß den Standards der C-Programmiersprache

Lesezeit: 8 Minuten

Cringes Benutzer-Avatar
schaudern

Ich möchte ein Strukturelement initialisieren, aufgeteilt in Deklaration und Initialisierung. Das habe ich:

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

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

Ist dies der Weg, eine lokale Variable von zu deklarieren und zu initialisieren? MY_TYPE nach C-Standards für Programmiersprachen (C89, C90, C99, C11 usw.)? Oder gibt es etwas Besseres oder zumindest Funktionierendes?

Aktualisieren Am Ende hatte ich ein statisches Initialisierungselement, in dem ich jedes Unterelement nach meinen Bedürfnissen festlegte.

  • Sie sollten wirklich eine bessere Antwort akzeptieren. Ich sehe, Sie mussten einen schlechten Codierungsleitfaden verwenden, aber Sie sollten anderen Leuten trotzdem nicht vorschlagen, dass dies der richtige Weg ist.

    – Karoly Horvath

    28. Juli 2012 um 9:43 Uhr


  • @KarolyHorvath Nun, die meisten guten Antworten sind spezifisch für C99. Vielleicht ist meine Frage ein Duplikat von stackoverflow.com/questions/6624975/… ?

    – schaudern

    29. Juli 2012 um 10:02 Uhr

  • Wenn das Ihre ursprüngliche Absicht war, dann wahrscheinlich ja, aber dann 1) wären die Stimmen sehr irreführend. 2) Von den Top-Suchtreffern ist dies die einzige, die den C99-Weg zeigt….. es wäre besser, diese Seite für C99-Demonstrationen wiederzuverwenden… (anscheinend haben Leute damit begonnen, diese Seite zu verlinken, um zu zeigen, wie es geht Tu es)

    – Karoly Horvath

    29. Juli 2012 um 11:02 Uhr


  • Interessant, dass die akzeptierte (und stark positiv bewertete) Antwort die Frage nicht wirklich beantwortet, selbst wenn sie ursprünglich gepostet wurde. Ausgewiesene Initialisierer gehen nicht auf das Problem des OP ein, nämlich auf Teilt die Deklaration aus der Initialisierung. Für C vor 1999 besteht die einzige wirkliche Lösung darin, jedem Mitglied zuzuweisen; für C99 und höher ist ein zusammengesetztes Literal, wie in CesarBs Antwort, die Lösung. (Natürlich wäre ein tatsächlicher Initialisierer mit oder ohne Bezeichner noch besser, aber anscheinend war das OP mit einem wirklich schlechten Codierungsstandard ausgestattet.)

    – Keith Thompson

    9. Juni 2013 um 6:39 Uhr

  • Genau genommen bezieht sich der Begriff „ANSI C“ nun auf den ISO-Standard 2011, den ANSI übernommen hat. In der Praxis bezieht sich der Begriff “ANSI C” jedoch häufig auf den (offiziell veralteten) Standard von 1989. Beispielsweise erzwingt “gcc -ansi” immer noch den Standard von 1989. Da ISO die Standards 1990, 1999 und 2011 veröffentlicht hat, ist es am besten, den Begriff „ANSI C“ zu vermeiden und sich auf das Datum des Standards zu beziehen, wenn die Möglichkeit einer Verwechslung besteht.

    – Keith Thompson

    9. Juni 2013 um 6:43 Uhr

Benutzeravatar von Philant
Philant

In (ANSI) C99 können Sie a ausgewiesener Initialisierer um eine Struktur zu initialisieren:

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

Andere Mitglieder werden als null initialisiert: „Ausgelassene Feldmitglieder werden implizit genauso initialisiert wie Objekte mit statischer Speicherdauer.“ (https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html)

  • super, danke. Sie können sie sogar verschachteln: static oxeRay2f ray = { .unitDir = { .x = 1.0f, .y = 0.0f } };

    – orion elenzil

    2. Mai 2011 um 0:00 Uhr


  • Das beantwortet die Frage überhaupt nicht. OP möchte die Initialisierung von der Deklaration trennen.

    – osven

    4. April 2018 um 20:09 Uhr

  • C99 != ANSI C – Das funktioniert also weder in C89 noch in C90.

    – Tim Wißmann

    13. Mai 2018 um 12:09 Uhr


  • C99 ist ANSI C, siehe hier

    – Cutberto Ocampo

    21. September 2018 um 5:29 Uhr


  • @CutbertoOcampo Ich verstehe, was jetzt passiert ist. Die ursprüngliche Frage war nach Lösungen in ANSI C gefragt, offensichtlich wollte er nur Antworten für C89. Im Jahr 2016 wurde die Frage bearbeitet und “ANSI C” entfernt, wodurch es jetzt schwer zu verstehen ist, warum diese Antwort und Kommentare “(ANSI) C99” erwähnen.

    – Etienne

    4. Juli 2019 um 12:08 Uhr

Benutzeravatar von CesarB
CesarB

Sie können es mit einem tun zusammengesetztes Literal. Laut dieser Seite funktioniert es in C99 (was auch als 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 };

Die Bezeichnungen in den Initialisierern sind optional; man könnte auch schreiben:

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

  • Also, designierte Initialisierer sind dafür da, wenn Sie gleichzeitig deklarieren und definieren, aber zusammengesetzte Literale, wenn Sie eine bereits deklarierte Variable definieren?

    – Geremia

    24. März 2016 um 19:09 Uhr

  • @Geremia Sie müssen in beiden Fällen zuerst die Struktur definieren, aber mit designierten Initialisierern machen Sie den Code lesbarer und widerstandsfähiger gegen Fehler, falls Änderungen an der Struktur vorgenommen werden.

    – hoijui

    18. Dezember 2017 um 7:05 Uhr

  • Das ist ein wenig knifflig. Viele Male (einige davon erfolgreich) habe ich versucht, bestimmte Initialisierer zu verwenden. Es ist jedoch erst jetzt klar geworden (dank Ihres und des Beispiels von @philant), dass ein Cast vorhanden sein muss, wenn der Initialisierer zum Zeitpunkt der Objekterzeugung nicht verwendet wird. Allerdings habe ich jetzt auch gelernt, dass wenn Initialisierer zu einem anderen Zeitpunkt als der Objekterstellung (wie in Ihrem Beispiel) verwendet werden, dies als a bezeichnet wird zusammengesetztes Literalnicht unbedingt a ausgewiesener Initialisierer. ideone.com/Ze3rnZ

    – sherrelbc

    28. Dezember 2017 um 12:23 Uhr


Benutzeravatar von Ron Nuni
Ron Nuni

Wie ich sehe, haben Sie bereits eine Antwort zu ANSI C 99 erhalten, also werde ich einen Knochen über ANSI C 89 werfen. Mit ANSI C 89 können Sie eine Struktur auf diese Weise initialisieren:

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

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

Beachten Sie unbedingt, dass in dem Moment, in dem Sie auch nur ein Objekt / eine Variable in der Struktur initialisieren, alle anderen Variablen auf den Standardwert initialisiert werden.

Wenn Sie die Werte in Ihrer Struktur nicht initialisieren, enthalten alle Variablen “Garbage-Werte”.

Viel Glück!

  • Ist es möglich, Variablen bei der Initialisierung zu verwenden?

    – Cyan

    20. Mai 2016 um 13:47 Uhr

  • @Cyan Es ist für Objekte mit automatischer Speicherdauer. Siehe 6.7.9 13) Zoll open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf . Für globale Objekte ist es ziemlich auf Literale beschränkt. Sie können nicht einmal andere globale Objekte verwenden, selbst wenn sie konstant sind.

    – PSkočik

    9. Oktober 2016 um 11:47 Uhr

  • Der einzige Unterschied zu C 99 besteht also darin, dass Sie die Bezeichnungen nicht festlegen können?

    – Akaisteph7

    24. Februar 2020 um 23:55 Uhr

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

würde gut in C99 tun

Benutzeravatar von PF4Public
PF4Öffentlichkeit

Programmiersprachenstandard C ISO/IEC 9899:1999 (allgemein bekannt als C99) ermöglicht die Verwendung von a ausgewiesener Initialisierer um Member einer Struktur oder Union wie folgt zu initialisieren:

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

Es ist definiert in paragraph 7Sektion 6.7.8 Initialization der Norm ISO/IEC 9899:1999 als:

Wenn ein Bezeichner die Form hat
. Kennung
dann muss das aktuelle Objekt (unten definiert) einen Struktur- oder Vereinigungstyp haben und der Bezeichner muss der Name eines Mitglieds dieses Typs sein.

Beachten Sie, dass paragraph 9 des gleichen Abschnitts heißt es:

Sofern nicht ausdrücklich anders angegeben, nehmen für die Zwecke dieses Unterabschnitts unbenannte Mitglieder von Objekten des Struktur- und Vereinigungstyps nicht an der Initialisierung teil. Unbenannte Mitglieder von Strukturobjekten haben auch nach der Initialisierung einen unbestimmten Wert.

In der GNU-GCC-Implementierung werden jedoch ausgelassene Elemente als null oder nullähnlicher typgerechter Wert initialisiert. Wie im Abschnitt angegeben 6.27 Ausgewiesene Initialisierer der GNU GCC-Dokumentation:

Ausgelassene Feldmitglieder werden implizit genauso initialisiert wie Objekte mit statischer Speicherdauer.

Der Microsoft Visual C++-Compiler sollte laut offiziellem Blogbeitrag seit Version 2013 bestimmte Initialisierer unterstützen C++-Konformitäts-Roadmap. Absatz Initializing unions and structs von Initialisierer Artikel in der MSDN Visual Studio-Dokumentation schlägt vor, dass unbenannte Mitglieder ähnlich wie bei GNU GCC mit nullähnlichen geeigneten Werten initialisiert werden.

ISO/IEC 9899:2011 Standard (allgemein bekannt als C11), der ISO/IEC 9899:1999 ersetzt hatte, behält die designierten Initialisierer unter Abschnitt 6.7.9 Initialization. Es behält auch paragraph 9 unverändert.

Neu ISO/IEC 9899:2018 Standard (allgemein bekannt als C18), der ISO/IEC 9899:2011 ersetzt hatte, behält die designierten Initialisierer unter Abschnitt 6.7.9 Initialization. Es behält auch paragraph 9 unverändert.

  • Ich glaube, “unbenanntes Mitglied” bedeutet nicht “ausgelassene Felder”, sondern “anonyme Mitglieder” wie die Gewerkschaft in struct thing { union { char ch; int i; }; };. Der Standard sagt später: „Wenn es weniger Initialisierer in einer in geschweiften Klammern eingeschlossenen Liste gibt, als es Elemente oder Mitglieder eines Aggregats gibt, oder weniger Zeichen in einem Zeichenfolgenliteral, das verwendet wird, um ein Array bekannter Größe zu initialisieren, als es Elemente im Array gibt, der Rest des Aggregats wird implizit genauso initialisiert wie Objekte mit statischer Speicherdauer.”

    – Auftauchen

    2. Juni 2019 um 7:28 Uhr


Benutzeravatar von Neuron
Neuron

Du hast es fast geschafft…

MY_TYPE a = { true, 15, 0.123 };

Schnell suche nach ‘struct initialize c’ zeigt mir das

  • Ich glaube, “unbenanntes Mitglied” bedeutet nicht “ausgelassene Felder”, sondern “anonyme Mitglieder” wie die Gewerkschaft in struct thing { union { char ch; int i; }; };. Der Standard sagt später: „Wenn es weniger Initialisierer in einer in geschweiften Klammern eingeschlossenen Liste gibt, als es Elemente oder Mitglieder eines Aggregats gibt, oder weniger Zeichen in einem Zeichenfolgenliteral, das verwendet wird, um ein Array bekannter Größe zu initialisieren, als es Elemente im Array gibt, der Rest des Aggregats wird implizit genauso initialisiert wie Objekte mit statischer Speicherdauer.”

    – Auftauchen

    2. Juni 2019 um 7:28 Uhr


Benutzeravatar von Neuron
Neuron

wie Ron Nuni sagte:

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

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

Eine wichtige Sache, die Sie sich merken sollten: In dem Moment, in dem Sie auch nur ein Objekt / eine Variable in der Struktur initialisieren, werden alle anderen Variablen auf den Standardwert initialisiert.

Wenn Sie die Werte in Ihrer Struktur nicht initialisieren (dh wenn Sie diese Variable nur deklarieren), werden all variable.members wird “Garbage-Werte” enthalten, nur wenn die Deklaration lokal ist!

Wenn die Erklärung ist global oder statisch (wie in diesem Fall), alle nicht initialisiert variable.members wird automatisch initialisiert zu:

  • 0 für Ganzzahlen und Fließkommazahlen
  • '\0' zum char (Natürlich ist das genauso wie 0und char ist ein ganzzahliger Typ)
  • NULL für Zeiger.

  • Interessant über das Lokale/Globale, dies gilt auch für struct tm-Zeitwerte. Ich hatte eine lokale und in einem Fall war die Sommerzeit eingeschaltet, in einem anderen nicht, nicht wegen irgendetwas, das ich getan habe. Ich habe DST (das tm_isdst-Feld) nicht verwendet, dies war von strptime, aber als ich in time_t konvertierte, waren einige eine Stunde frei.

    – Alan Corey

    13. Juni 2017 um 20:01 Uhr

1428160cookie-checkSo initialisieren Sie eine Struktur gemäß den Standards der C-Programmiersprache

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy