Allgemeine Fragen zu Strukturen



  • Hallo,

    ich hätte mal ein paar ganz allgemeine Fragen zu Strukturen.

    Die erste Frage bezieht sich auf das Kopieren von Strukturen. Angenommen ich habe den folgenden Codeausschnitt:

    struct test
    {
        int a; 
        int b;
        char c;
    }
    
    struct test myStruct1; 
    myStruct1.a = 10; 
    myStruct1.b = 20; 
    myStruct1.c = 'a'; 
    
    struct test myStruct2; 
    myStruct2 = myStruct1;
    

    Steht dann in myStruct2 tatsächlich alles was in myStruct1 auch steht? Oder muss ich jedes Element extra kopieren? Also sowas wie ein Kopier-Konstruktor für Strukturen. Gesetzt dem Fall, dass tatsächlich die komplette Struktur kopiert werden würde: Angenommen, in der Struktur ist ein Zeiger enthalten. Dann wird ja der Zeiger 1:1 kopiert, richtig? D.h. wenn ich in myStruct1 den Wert auf den der Zeiger zeigt ändere, habe ich automatisch auch den Wert auf den der Zeiger in myStruct2 zeigt geändert oder?

    Die zweite Frage bezieht sich auf die Deklaration einer Struktur, und zwar in etwa so:

    typedef struct _myTestStruct
    {
    	HANDLE   hMyHandle;
    	int      a;
    	char     myCharArray[10];
    
    }myTestStruct;
    

    So etwas habe ich schon ganz oft gesehen, und nie so richtig verstanden. Also erstmal wir ja mit typedef ein vollkommen neuer Typ deklariert. D.h. in Zukunft kann ich eine solche Struktur ganz einfach so anlegen:

    myTestStruct struct1;
    

    Oder vielleicht so?

    _myTestStruct struct1;
    

    Wofür ist der Unterstrich? Ist das einfach so eine Naming konvention oder hat das auch einen Grund?

    Bin total verwirrt... 😕



  • SonntagsGast schrieb:

    Steht dann in myStruct2 tatsächlich alles was in myStruct1 auch steht?

    ja

    SonntagsGast schrieb:

    Also sowas wie ein Kopier-Konstruktor für Strukturen.

    sowas gibt es in C nicht.

    SonntagsGast schrieb:

    Angenommen, in der Struktur ist ein Zeiger enthalten. Dann wird ja der Zeiger 1:1 kopiert, richtig?

    richtig, d.h. der Wert/Adresse worauf der Zeiger zeigt, nicht jedoch den gezeigten Inhalt.

    SonntagsGast schrieb:

    D.h. wenn ich in myStruct1 den Wert auf den der Zeiger zeigt ändere, habe ich automatisch auch den Wert auf den der Zeiger in myStruct2 zeigt geändert oder?

    nein, weil du nur eine Kopie veränderst. Wenn du aber über den Zeiger den Inhalt veränderst, dann merkt man die Änderung an beiden Struct-Instanten

    struct foo {
     ...
     char *name;
    };
    
    struct foo a,b;
    a.name = malloc(9);
    strcpy(a.name, "supertux");
    ...
    b = a;
    

    dann zeigen b.name und a.name beide auf der selben Stellen. Wenn du sowas machst wie a.name = "hallo" , dann veränderst du nur den Zeiger von a . Wenn du aber strcpy(a.name, "hallo"); machst, dann veränderst du das, worauf der Zeiger zeigt. Weil b.name auf diesselbe Stelle zeigt wie a.name , dann wird printf("%s\n", b.name); "hallo" ausgeben.

    struct bar {
     ...
     char name[1024];
    };
    
    struct bar a,b;
    strcpy(a.name, "supertux");
    ...
    b = a;
    

    hier hast du keinen Zeiger, sondern ein Array. Ein strcpy(a.name, "hallo"); führt nicht dazu, dass b.name auch "hallo" speichert.

    SonntagsGast schrieb:

    So etwas habe ich schon ganz oft gesehen, und nie so richtig verstanden. Also erstmal wir ja mit typedef ein vollkommen neuer Typ deklariert. D.h. in Zukunft kann ich eine solche Struktur ganz einfach so anlegen:

    myTestStruct struct1;
    

    Oder vielleicht so?

    _myTestStruct struct1;
    

    Wofür ist der Unterstrich? Ist das einfach so eine Naming konvention oder hat das auch einen Grund?

    Bin total verwirrt... 😕

    mit typedef deklarierst du einen neuen Typ abhängig von einem bereits deklarierten Typ. Man benutzt typedef um:

    1. Konsistenz im Code zu behalten
      z.b. die FILE Struktur von stdio.h. Was hinter FILE steckt, muss man als Anwender wissen. Wenn die Implementierung von FILE sich von struct fileA auf struct fileB ändert, dann müsste man überall im Code den Struct Namen anpassen. Weil man jedoch das 'getypedef'-FILE benutzt, muss man das nicht.

    2. manche um C++isch Code zu schreiben, wo man das 'struct' nicht notwendig braucht.



  • supertux schrieb:

    SonntagsGast schrieb:

    Also sowas wie ein Kopier-Konstruktor für Strukturen.

    sowas gibt es in C nicht.

    struct s
    {
       int a;
       char *b;
       char c;
    } s1 = {123, "hello", 'x'};  // original 
    
    int main()
    {
      struct s s2 = s1; // kopie
      printf ("%d %s %c\n", s2.a, s2.b, s2.c);
    }
    

    🙂



  • die Rede war nicht von Kopien sondern von einem Kopier-Konstruktor (im C++schen Sinne), oder hab ich da was falsch verstanden?



  • ~fricky schrieb:

    supertux schrieb:

    SonntagsGast schrieb:

    Also sowas wie ein Kopier-Konstruktor für Strukturen.

    sowas gibt es in C nicht.

    struct s
    {
       int a;
       char *b;
       char c;
    } s1 = {123, "hello", 'x'};  // original 
    
    int main()
    {
      struct s s2 = s1; // kopie
      printf ("%d %s %c\n", s2.a, s2.b, s2.c);
    }
    

    🙂

    Deine Kopie ist nur halbgar.
    🙂



  • supertux schrieb:

    die Rede war nicht von Kopien sondern von einem Kopier-Konstruktor (im C++schen Sinne), oder hab ich da was falsch verstanden?

    ne, ich hab' das falsch verstanden. sowas was mein code macht, macht der OP sowieso schon. vielleicht sollte ich mir mal angewöhnen, threads vollständig zu lesen bevor ich was poste.

    Tachyon schrieb:

    Deine Kopie ist nur halbgar.

    was stört dich? wird doch alles kopiert.
    🙂



  • Hallo,

    vielen Dank für die Antworten. Das letzte, was ich jetzt immer noch nicht so recht verstanden habe ist, wofür der Unterstrich in unten stehendem Code steht?! Ich sehe da einfach keinen Sinn darin, ich könnte doch genauso gut den Unterstrich zweimal oder auch keinmal verwenden?

    typedef struct _myTestStruct 
    { 
        HANDLE   hMyHandle; 
        int      a; 
        char     myCharArray[10]; 
    
    }myTestStruct;
    


  • SonntagsGast schrieb:

    Ich sehe da einfach keinen Sinn darin, ich könnte doch genauso gut den Unterstrich zweimal oder auch keinmal verwenden?

    Gut deine Augen sind 😉

    @ fricky

    Tachyon wird entweder auf padding bytes, oder auf das nicht kopierte Zeugs auf das der Zeiger zeigt hinaus wollen.



  • Du kannst sogar auf die Unterstriche ganz verzichten.
    Guckst du, so:

    typedef struct A
    {
        int i;
    }A;
    

    Vielleicht verwirrt es noch weniger, wenn du auf das 'Tagding' ganz verzichtest:

    typedef struct
    {
        int i;
    }B;
    

    MfG,
    k.k.



  • SonntagsGast schrieb:

    Hallo,

    vielen Dank für die Antworten. Das letzte, was ich jetzt immer noch nicht so recht verstanden habe ist, wofür der Unterstrich in unten stehendem Code steht?!

    was ich nicht verstehe, wofür der 'S' Buchstabe bei deinem Nick steht?!

    _ ist Teil des Namen, genauso gut könnte MickeyMouse oder Mickey_Mouse stehen. Eigentlich ist es nicht erlaubt einen Bezeichnernamen mit einem (doppelten) Unterschrich zu verwenden, weil diese Namen reserviert sind aber wenig Leute halten sich daran.

    Tim schrieb:

    @ fricky

    Tachyon wird entweder auf padding bytes, oder auf das nicht kopierte Zeugs auf das der Zeiger zeigt hinaus wollen.

    da frag ich mich, wie löst der Compiler diese Aufgabe?

    struct wasauchimmmer a,b;
    ...
    b = a;
    

    ist sowas irgendwo definiert? Ist das äquivalent zu memmove(&a, &b, sizeof(a)); oder zu b.member1 = a.member1; b.member2 = a.member2;... ?



  • Sehe ich das dann richtig, dass nach einem typedef wie unten zu sehen _myTestStruct und myTestStruct vollkommen gleichbedeutend sind?

    So dass ich nach dem unten stehenden Codefragment eine Struktur diesen Typs so

    _myTestStruct nummer1;
    

    oder so

    myTestStruct nummer2;
    

    deklarieren könnte? D.h. "nummer1" und "nummer2" sind Strukturen des gleichen Typs?!

    typedef struct _myTestStruct 
    { 
        HANDLE   hMyHandle; 
        int      a; 
        char     myCharArray[10]; 
    
    }myTestStruct;
    


  • Nein.
    Im Zweifelsfall kannst du das auch ausprobieren.

    typedef struct 
    {
        int i;
    }C;
    
    typedef struct _D
    {
        int i;
    }D;
    
     C c; // Ok
     D d; // Ok
     _D _d; // Fehler
    

    Das _D ist ein Etikett, ein structure tag und kann weggelassen werden.
    🙂



  • supertux schrieb:

    Tim schrieb:

    @ fricky

    Tachyon wird entweder auf padding bytes, oder auf das nicht kopierte Zeugs auf das der Zeiger zeigt hinaus wollen.

    da frag ich mich, wie löst der Compiler diese Aufgabe?

    struct wasauchimmmer a,b;
    ...
    b = a;
    

    ist sowas irgendwo definiert? Ist das äquivalent zu memmove(&a, &b, sizeof(a)); oder zu b.member1 = a.member1; b.member2 = a.member2;... ?

    Die Implementierung kann es sich raussuchen. Oder hast du was anderes erwartet? 🤡



  • supertux schrieb:

    da frag ich mich, wie löst der Compiler diese Aufgabe?

    struct wasauchimmmer a,b;
    ...
    b = a;
    

    schreib mal entsprechenden code und disassembliere den compiler-output. du wirst sehen, dass 'heimlich' eine kopier-routine aufgerufen wird. das kann durchaus 'memcpy' sein.
    🙂



  • Tim schrieb:

    Die Implementierung kann es sich raussuchen. Oder hast du was anderes erwartet? 🤡

    dass es Frieden auf Erden gibt 😃 ich dachte nur, vielleicht ist sowas irgendwo genau spezifiziert.

    schreib mal entsprechenden code und disassembliere den compiler-output. du wirst sehen, dass 'heimlich' eine kopier-routine aufgerufen wird. das kann durchaus 'memcpy' sein.

    hab grade jetzt keine Lust dazu 😉


Anmelden zum Antworten