struct Foo und typedef struct Foo_



  • Sind wir im Religionsunterricht?
    "Weil es halt so ist, weil es halt so in der Bibel (der C-ISO-Standard) steht"

    Wieso wurde das so in den C-ISO-Standard aufgenommen? Hat man eine Muenze geworfen, Kopf ist das man "struct" vor dem Struct hinschreiben muss, bei Zahl nicht?

    typedef ist da, um sich einen Datentyp zu erstellen, deswegen brauchst du das 'struct' danach nicht mehr, weil der Compiler dann weiß, dass es sich dabei um einen "struct {}" handelt.

    Also der Compiler weis nicht das Foo ein struct ist, obwohl ich ihn als struct Foo {}; definiert habe?



  • DEvent schrieb:

    Wieso wurde das so in den C-ISO-Standard aufgenommen? Hat man eine Muenze geworfen, Kopf ist das man "struct" vor dem Struct hinschreiben muss, bei Zahl nicht?

    Philosophisch wäre genauso die Frage "wieso hätten sie es nicht so aufnehmen sollen". Daher bringt es absolut nichts sich darüber den Kopf zu zerbrechen. Vermutung meinerseits: Man hat einfach nicht die Möglichkeit bedacht, oder hat absichtlich nicht gewollt, dass ein Struct-Name gleichzeitig ein Typ-Name wird.



  • "struct" ist in C kein Typ. "struct name" aber schon (int == int, struct != struct).



  • LordJaxom schrieb:

    Man hat einfach nicht die Möglichkeit bedacht, oder hat absichtlich nicht gewollt, dass ein Struct-Name gleichzeitig ein Typ-Name wird.

    warum sollte man bei 'struct' eine ausnahme machen, wenn's z.b. bei 'enum' und 'union' anders wäre? das fände ich ziemlich inkonsistent und schliesslich, wer schreibfaul ist, der kann ja zu 'typedef' greifen.
    anderseits würde es bestimmt funktionieren, wenn man struct/enum/union weglassen würde. ich kann mir keinen nachteil vorstellen, aber die iso/ansi-verfasser sind bestimmt schlauer als ich, denn sonst hätten sie's bestimmt anders gemacht.
    🙂



  • DEvent schrieb:

    Wieso wurde das so in den C-ISO-Standard aufgenommen? Hat man eine Muenze geworfen, Kopf ist das man "struct" vor dem Struct hinschreiben muss, bei Zahl nicht?

    Der ISO-Standard ist von 1990, C ist in den 70ern entwickelt worden. Es dürfte einleuchten, dass man dort größtenteils keine neuen Entscheidungen getroffen hat, sondern existierende Implementationen als Grundlage genommen hat.



  • anderseits würde es bestimmt funktionieren, wenn man struct/enum/union weglassen würde. ich kann mir keinen nachteil vorstellen, aber die iso/ansi-verfasser sind bestimmt schlauer als ich, denn sonst hätten sie's bestimmt anders gemacht.

    Vielleicht ist zu der Zeit als C entwickelt wurde auch einfach niemand auf die Idee gekommen, ein Struct-Tag auch gleich als Symbol in die Symboltabelle aufzunehmen, weil es nicht notwendig schien. In C++ wollte man vielleicht das Verhalten integraler Typen für Klassen (Operatorenüberladung etc.) imitieren.

    Aber das ist und bleibt Spekulation, solange nicht jemand nen Interview mit den Mitgliedern des 1989er-ANSI-Komitees arrangiert 🙂



  • weglass-freak schrieb:

    anderseits würde es bestimmt funktionieren, wenn man struct/enum/union weglassen würde.

    Oh, struct und union brauche ich wirklich, die Alternativen wären wirklich BASIC- mäßig zerfledderte Konstruktionen.
    Wenn ich ehrlich bin, habe ich außer zu akademischen Zwecken (mal probiert halt) noch nie typedef oder enum eingesetzt, die waren wirklich verzichtbar. Enumerationen bilde ich per define ab, structs und Funktionspointer schreibe ich lieber aus, damit mir auch später klar ist: Hoppla, denk' nach, was Du da tust.

    Asche über mein Haupt, wenn ich da dem C- Puristen auf die Zehen latsche, aber da ich nie aufhören möchte, zu lernen: Inwiefern sollen typedef und enum unverzichtbar sein?



  • pointercrash() schrieb:

    Enumerationen bilde ich per define ab,

    geht ja auch, aber ich finde bei enums das automatische hochzählen praktisch und dass der compiler meckert, wenn man hardcodierte werte doppelt hat. bei #defines haste ja diese compilerunterstützung nicht.

    pointercrash() schrieb:

    structs und Funktionspointer schreibe ich lieber aus...

    naja, es gibt schon echt fiese konstruktionen, die ohne 'typedef' super-hässlich und unleserlich sind.

    pointercrash() schrieb:

    Inwiefern sollen typedef und enum unverzichtbar sein?

    das sagt ja keiner. ich meinte das

    enum lala
    {
      A,B,C
    };
    
    union puh
    {
     int a;
     char c;
    };
    ...
    enum lala l;
    union puh p;
    ...
    

    also beim anlegen von instanzen muss man 'enum' und 'union' hinschreiben, sonst frisst's der compiler nicht. normalerweise aber könnte es auch ohne gehen. ich wüsste jedenfalls keinen nachteil, ausser einer vielleicht schlechteren lesbarkeit. aber die hat man ja auch, wenn man's 'typedef'd' und miese typnamen wählt.
    🙂



  • naja, es gibt schon echt fiese konstruktionen, die ohne 'typedef' super-hässlich und unleserlich sind.

    In C gehts ja noch, aber in C++ wirds wegen Templates schon unuebersichtlich.



  • DEvent schrieb:

    naja, es gibt schon echt fiese konstruktionen, die ohne 'typedef' super-hässlich und unleserlich sind.

    In C gehts ja noch, aber in C++ wirds wegen Templates schon unuebersichtlich.

    mag sein, aber auf c++ kann man zum glück so gut wie immer verzichten.
    🙂



  • pointercrash() schrieb:

    Inwiefern sollen typedef und enum unverzichtbar sein?

    Unverzichtbar sicher nicht. Aber ein typedef ist u.a. sehr geschickt weil man manchmal halt eben die Implementierung hinter dem Typ verstecken will. Beispiel FILE . Man braucht überhaupt nicht zu wissen was sich dahinter verbirgt, struct, union, bitfield, int. Alles läuft über die gegebenen Schnittstellen (fopen, fclose, fwrite, ...) ab.



  • es ist doch ein essentieller Unterscheid, ob ich von C oder von C++ rede, oder nicht? Das eine ist eine prozedurale Programmiersprache aus den 70er Jahren, mit der ich absolut Speicher und CPU effizient Coden kann - damals hat man auch die Notwenigkeit dafür noch gehbat. Zu Zeiten von C++ und C#, was nunmal der Objektorientierung angehört wird kaum mehr Wert auf Ressourceneffizienz gelegt. Man kann allerdings objektorientiert viel schneller kompelxe Programme stricken, ohne sich Gedanken machen zu müssen, wie kopmlexe Datentypen intern aussehen, wie sie behandelt werden müssen usw.! Die Anforderungen haben sich also im Laufe der von Ressourcenknappheit auf der hardwareseite nach Zeitknappheit bei der Entwicklung verlagert - und daraus resultiert nun mal eine vereinfachte Benutzung der Programmiersprache bei der gleichen Aufgabenstellung.

    Und zu dem struct / enum oder typedef und nicht struct / enum: wenn man professionell programmiert und dabei auf eine gewisse Lesbarkeit und Wiederverwendbarkeit der eigenen Quelltexte achten muss kann man sicherlich auch die typedefs nicht allzu gut einsetzen, um dem "Wiederverwender" zu ermöglichen, den Quelltext sauber zu lesen ohne erst jedes Header-File studieren zu müssen. Wenn man allerdings privat codet und weiß, man wird nur selbst jemals den Quelltext zu Gesicht bekommen und man kann sich merken, wie man seine eigenen Datentypen, Strukturen, Enumerationen und so weiter definiert hat, dann kann man sie ja durchaus dem Compiler auch mit typedef bekannt geben.

    Soviel zu meiner Meinung zu dem Thema - ob sie nun einer wissen will oder nicht!



  • @ Tim:

    Das Problem dabei ist: FILE ist Well-Known und kann überall nachgeschaut werden. Wenn ich mir allerdings jetzt selbst eine Structur schreibe, die beispielsweise einen Mitarbeiter mit allen Attributen definiere sollte ich einem potenziellen Leser meines Codes schon die Möglichkeit geben, nach zu vollziehen, was ich tue und wie, oder meinst du nicht?



  • AnonymousCoder schrieb:

    es ist doch ein essentieller Unterscheid, ob ich von C oder von C++ rede, oder nicht?

    Wir sind hier im C-Unterforum, von daher ist klar worüber wir reden. Womit ich den weiteren Absatz (den du btw. nochmal überdenken solltest) nicht weiter kommentieren werde.

    AnonymousCoder schrieb:

    Und zu dem struct / enum oder typedef und nicht struct / enum: wenn man professionell programmiert und dabei auf eine gewisse Lesbarkeit und Wiederverwendbarkeit der eigenen Quelltexte achten muss kann man sicherlich auch die typedefs nicht allzu gut einsetzen, um dem "Wiederverwender" zu ermöglichen, den Quelltext sauber zu lesen ohne erst jedes Header-File studieren zu müssen.

    Bezüglich der Lesbarkeit: Das ist im Zweifelsfall eine Meinungssache und hat mit "professioneller Programmierung" erstmal nichts zu tun. Aber wenn du Header-Files lesen musst, um einen Typen genauer zu identifizieren (Struktur, Enumeration, plain int, ...) dann fehlt dem Projekt zumindest ein Aspekt der "professionellen Programmierung", nämlich eine ordentliche Doku. Und in der musst du so oder so nachschauen, wenn du wissen willst was ein Typ T genau ausmacht (welche Member, welche Konstanten kennt das enum, ...), egal ob du nun schon weisst dass es ein struct oder ein enum oder sonstwas ist.

    Bezüglich der Wiederverwendbarkeit: Du schreibst ein Modul welches andere Entwickler benutzen müssen. Denken wir an ein theoretisches Objekt (z.B. etwas wie ein FILE) mit dem die Leute arbeiten. Wir nennen es struct obj , mit dem Konstruktor struct obj *obj_init(void) , dem Destruktor void obj_kill(struct obj *object) und ein paar anderen Methoden wie z.B. void obj_send_data(struct obj *object, int data) . Nun kann es im Laufe der Entwicklung passieren, dass sich deine Implementierung ändert, so merkst du (aus welchen Gründen auch immer) dass die Implementierung als struct obj Nachteile hat und willst nur noch eine ID (vom Typ int z.B.) in der Schnittstelle verwenden. Natürlich musst du nun alle deine Funktionen anpassen, aber viel schlimmer noch, die Benutzer deines Moduls müssen es ebenfalls. Hättest du von Anfang an ein typedef struct obj obj_t benutzt, könntest du jetzt einfach ein typedef int obj_t machen und die Schnittstelle hat sich nicht geändert.



  • AnonymousCoder schrieb:

    es ist doch ein essentieller Unterscheid, ob ich von C oder von C++ rede, oder nicht? Das eine ist eine prozedurale Programmiersprache aus den 70er Jahren, mit der ich absolut Speicher und CPU effizient Coden kann - damals hat man auch die Notwenigkeit dafür noch gehbat.

    glaubst du wirklich, dass diese notwendigkeit heute nicht mehr besteht?
    C ist zwar ein steinalter hund, aber auf dem gebiet der hardwarenahen system- und low-level programmierung auch heute noch unersetzlich.
    🙂



  • AnonymousCoder schrieb:

    @ Tim:

    Das Problem dabei ist: FILE ist Well-Known und kann überall nachgeschaut werden. Wenn ich mir allerdings jetzt selbst eine Structur schreibe, die beispielsweise einen Mitarbeiter mit allen Attributen definiere sollte ich einem potenziellen Leser meines Codes schon die Möglichkeit geben, nach zu vollziehen, was ich tue und wie, oder meinst du nicht?

    Wieso sollte es bei einem FILE anderes sein als mein eigenes Object FOO?

    Ich weis z.B. absolut nicht was sich hinter FILE versteckt, interessiert mich auch nicht im geringstem. Ich weis nur das ich es braucht fuer fopen(), fclose() usw. und wenn ich irgendwann eine foo(FILE* file) habe, dann gehe ich davon aus das derjenige der foo() implementiert hat, genau weis wie man FILE benutzt.

    Aber schoen das man mir die Frage beantwortet hat ob man

    struct Foo {} 
    // oder
    typedef struct _Foo {} Foo;
    

    schreiben soll. Werd bei naechster Gelegenheit meine Programme auf letzeres umstellen.

    Uebrigens programmiere ich in C (fast) genauso Objectorientiert wie in Java/C++. Mir fehlt da nur dass man keine privaten Attribute in C hat, bzw. ich weis nicht wie man private Attribute am besten implementieren kann.



  • DEvent schrieb:

    Uebrigens programmiere ich in C (fast) genauso Objectorientiert wie in Java/C++.

    immer? wofür benutzt du denn C?

    DEvent schrieb:

    Mir fehlt da nur dass man keine privaten Attribute in C hat, bzw. ich weis nicht wie man private Attribute am besten implementieren kann.

    naja, access levels wie z.b. in Java sind ja eigentlich nur in zusammenhang mit vererbung wichtig. in deinen C-objekten könntest du objektinterne attribute verstecken, indem du erst gar keine funktionen bereitstellst, die diese members direkt verändern.
    🙂



  • DEvent schrieb:

    Mir fehlt da nur dass man keine privaten Attribute in C hat, bzw. ich weis nicht wie man private Attribute am besten implementieren kann.

    selbst das hab ich schon mal gesehen (bei gtk)

    In KlasseEins.h. Die einzige Datei die für die Benutzer der Bibliothek öffentlich ist.

    /* KlasseEins.h */
    
    struct c_KlasseEins {
      /* private Attribute */
      void *privat;
    
      /* öffentlich Attribute */
      int x;
      int y;
      ...
    };
    
    typedef struct c_KlasseEins KlasseEin;
    

    In KlasseEin.c

    /* KlasseEins.c */
    
    #include <mylib/KlasseEins.h>
    
    struct c_KlasseEins_privat {
      int privat_attrib1;
      double privat_attrib2;
      ...
    };
    
    typedef struct c_KlasseEins_privat KlasseEins_privat;
    
    /* Konstruktor */
    KlasseEins *init_KlasseEins(...)
    {
        KlasseEins *tmp;
        KlasseEins_privat *privat;
    
        tmp = malloc(sizeof(*tmp));
    
        if(tmp == NULL) return NULL;
    
        privat = malloc(sizeof(*privat));
    
        if(privat == NULL)
        {
            free(tmp);
            return NULL;
        }
    
        /* öffentliche Attribute initialisieren */
       tmp->...
    
       /* private Attribute initialisieren */
    
       privat->...;
    
       tmp->privat = privat;
    
       return tmp;
    }
    
    int KlasseEins_tutirgendwas(KlasseEins *K)
    {
        KlasseEins_privat *privtat;
    
        if(K == NULL) return 0;
    
        /* auf private Attribute zugreifen */
        privat = K->privat;
        ...
    }
    

    Da KlasseEins_privat nur in der C Datei definiert ist, weiß der Bentutzer der Bibliothek (der KlasseEins.h includiert) gar nicht wie 'KlasseEins->privat' aussieht und somit werden diese Attribute privat. Das ist sogar mit Vererbung kompatibel.



  • OOP-freak schrieb:

    DEvent schrieb:

    Uebrigens programmiere ich in C (fast) genauso Objectorientiert wie in Java/C++.

    immer? wofür benutzt du denn C?

    Wieso soll ich die Vorteile hardwarenaher Programmierung und OOP nicht kombinieren?

    @supertux danke 🙂



  • DEvent schrieb:

    OOP-freak schrieb:

    DEvent schrieb:

    Uebrigens programmiere ich in C (fast) genauso Objectorientiert wie in Java/C++.

    immer? wofür benutzt du denn C?

    Wieso soll ich die Vorteile hardwarenaher Programmierung und OOP nicht kombinieren?

    weil OOP nicht immer was bringt. manchmal ist es einfach nur sinnloser ballast.
    🙂


Anmelden zum Antworten