Teilweises Initialisieren einer C-Struktur

Lesezeit: 4 Minuten

Benutzer-Avatar
Pavian

Dies Verknüpfung besagt: “Wenn ein automatisches Array oder eine Struktur einen Teilinitialisierer hat, wird der Rest auf 0 initialisiert”. Ich beschloss, das auszuprobieren, was ich gelesen hatte, und schrieb den folgenden Code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    //int arr[3] = {2};  // line no. 7

    struct s {
        int si;
        int sj;
    };

    struct s myStruct;
    myStruct.si = 9;
    printf("%d\n", myStruct.sj);
}

Ich verstehe nicht warum 4096 (was meiner Meinung nach ein “Müll” -Wert ist) wird gedruckt, wenn ich es auskommentiere line no. 7 und ich bekomme 0 wenn ich auskommentiere line no. 7. Ich glaube nicht arr Erklärung hat etwas damit zu tun main()‘s Aktivierungsdatensatz (bzw myStruct), die so aussehen sollte (vorausgesetzt wir haben line no. 7 unkommentiert):

---------------
|  Saved PC   |
---------------
|  arr[2]     |
---------------
|  arr[1]     |
---------------
|  arr[0]     |
---------------
|  si         |
---------------
|  sj         |
---------------

Kann mir bitte jemand erklären, was mir hier fehlt?

  • Siehe auch: stackoverflow.com/q/28545491/694576

    – alk

    31. Mai 2016 um 14:28 Uhr

Benutzer-Avatar
dbusch

Wenn Sie dies tun:

struct s myStruct;
myStruct.si = 9;

Du bist nicht initialisieren myStruct. Du erklärst es ohne Initialisiererund führen Sie dann eine Anweisung aus, um ein Feld festzulegen.

Da die Variable nicht initialisiert ist, ist ihr Inhalt undefiniert, und das Lesen ist es undefiniertes Verhalten. Dies bedeutet, dass scheinbar nicht zusammenhängende Änderungen dieses Verhalten ändern können. Fügen Sie in Ihrem Beispiel eine zusätzliche Variable hinzu passiert verursachen myStruct.sj 0 sein, aber es gibt keine Garantie dafür, dass dies der Fall sein wird.

Zu initialisieren eine Variable, müssen Sie ihr einen Wert zu der Zeit geben, zu der sie ist definiert:

struct s myStuct = { 9 };

Sobald Sie dies tun, sehen Sie den Inhalt von myStruct.sj auf 0 gesetzt. Dies wird gemäß Abschnitt 6.7.8 von gewährleistet die C-Norm (mit spezieller Hervorhebung für diesen Fall):

10 Wenn ein Objekt mit automatischer Speicherdauer nicht explizit initialisiert wird, ist sein Wert unbestimmt. Wenn ein Objekt mit statischer Speicherdauer nicht explizit initialisiert wirddann:

– wenn es einen Zeigertyp hat, wird es mit einem Nullzeiger initialisiert;

wenn es einen arithmetischen Typ hat, wird es auf (positiv oder vorzeichenlos) Null initialisiert;

wenn es sich um ein Aggregat handelt, wird jedes Mitglied (rekursiv) gemäß diesen Regeln initialisiert;

– Wenn es sich um eine Union handelt, wird das zuerst genannte Element (rekursiv) gemäß diesen Regeln initialisiert.

21 Wenn in einer in geschweiften Klammern eingeschlossenen Liste weniger Initialisierer vorhanden sind, als Elemente oder Mitglieder eines Aggregats vorhanden sindoder weniger Zeichen in einem Zeichenfolgenliteral, das zum Initialisieren eines Arrays bekannter Größe verwendet wird, als Elemente im Array vorhanden sind, der Rest des Aggregats wird implizit genauso initialisiert wie Objekte mit statischer Speicherdauer.

  • declare it without an initializer ist eine nette Art, es auszudrücken. Als Randnotiz habe noch keine der Antworten erklärt I get 0 when I uncomment line no. 7

    – sjsam

    31. Mai 2016 um 14:36 ​​Uhr


  • Compileroptionen können so eingestellt werden, dass der gesamte Speicher auf Null initialisiert wird, und einige Betriebssysteme können dies tun, aber myStruct.sj könnte alles sein, wie @dbush betont. Wenn myStruct.sj ist ein Zeiger, als der nicht initialisierte Wert alle möglichen Probleme verursachen könnte, dies ist mir passiert.

    – Michael Shopsin

    31. Mai 2016 um 15:16 Uhr

  • @MichaelShopsin: Könnten Sie ohne festgelegte Compiler-Optionen ein Beispiel für geben some operating systems that do so. Ich glaube, sowohl Linux als auch Windows werden dies nicht tun.

    – sjsam

    31. Mai 2016 um 15:27 Uhr

  • Im Verhältnis zu “Ich bekomme 0, wenn ich Zeile Nr. auskommentiere. 7“: Als dbush-Notizen (“scheinbar nicht zusammenhängende Änderungen … das Hinzufügen einer zusätzlichen Variablen führte dazu, dass myStruct.sj 0 war“), per Definition ist es undefiniert, in plausible Praxis es ist das, was zufällig in diesem Stückchen Erinnerung geblieben ist. Wenn Sie die Größe Ihrer variieren würden arr[3] Definition (wodurch variiert wird, wie weit der Speicher herunterfällt si und sj in Ihrer Speicherkarte sind), Sie kann erhalten Sie eine ganze Reihe von Werten.

    – TripeHound

    31. Mai 2016 um 16:16 Uhr


  • @Spotlight Das hatte OP ursprünglich. Er setze si und da ich dachte, es sei eine Initialisierung, erwartet sj 0 sein.

    – dbusch

    31. Mai 2016 um 18:53 Uhr

Benutzer-Avatar
Sourav Ghosh

In Ihrem Fall,

 myStruct.si = 9;

ist ein Abtretung Aussage, nicht Initialisierung. In diesem Fall sind die Strukturvariable (und die entsprechenden Variablen) nicht initialisiert. Somit lesen Sie am Ende den Wert einer nicht initialisierten Variablen sjwas dazu führt undefiniertes Verhalten.

Du kannst es versuchen

struct s myStruct = {9};

zu sehen implizite Initialisierung in Aktion.

Das ist kein Initialisierer – Ihre Struktur ist nicht initialisiert, dann weisen Sie nur noch zu si. sj bleibt uninitialisiert.

Das Buch bezieht sich auf diese Art von Code:

struct s myStruct = {9};

… wo sj ist garantiert 0.

Dies ist im Grunde ein – mehr oder weniger – vollständiges Beispiel für die großartigen Antworten, die andere bereits gegeben haben.

#include<stdio.h>

struct{
  int a;
  int b;
}obj1={.a=0}; //Partial initialization

typedef struct struct_B{
  int a;
  int b;
}struct_B;

int main(void)
{
  printf("obj1.b : %d\n",obj1.b);
  struct_B obj2={.b=1,.a=0,0}; // b's first value is overridden here as 0 immediately follows a
  printf("obj2.b : %d\n",obj2.b);
  struct_B obj3={0}; //Partial initialization, here the '0' value is meant for a as it comes first in the declaration
  printf("obj3.b : %d\n",obj3.b);
  struct_B obj4={.a=0}; //Partial initialization
  printf("obj4.b : %d\n",obj4.b);
  return 0;
}

Ausgabe:

obj1.b : 0
obj2.b : 0
obj3.b : 0
obj4.b : 0

1369830cookie-checkTeilweises Initialisieren einer C-Struktur

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

Privacy policy