Identische typedefs möglich?



  • ZzetT schrieb:

    Diese Idee habe ich mal umgesetzt. Jetzt erhalte ich jedoch die gleichen Fehlermeldungen als wenn ich die doppelten Typen auskommentieren würde. Könnte es sein, dass die define-Makros global gelten und nicht nur für eine Datei? Damit meine ich, wenn z.B. eine Datei A Header B und C einbindet klappt es, aber wenn danach eine Datei D z.B. nur C einbindet, dann wäre das Symbol DEF_UInt32 schon definiert und er würde den Typen nicht mehr deklarieren und somit würde er für D fehlen oder habe ich da einen Denkfehler?

    ich verstehe nicht so sehr was du genau meinst. Angenommen, wir haben B.h und C.h wie oben

    /* datei1.c */
    #include "B.h"
    
    /* an der Stelle liest der Präprozessor die Datei B.h und ersetzt die Zeile 
    mit dem Inhalt der Datei. Wenn DEF_UInt32 dann wird DEF_UInt32 definiert und die typedef Zeile ist ebenfalls sichtbar. */
    
    #inlcude "C.h"
    
    /* an der Stelle liest der Präprozessor die Datei C.h und ersetzt die Zeile 
    mit dem Inhalt der Datei. Da DEF_UInt32 bereits definiert ist, wird der Block ignoniert, und UInt32 wird nicht nochmal typisiert. */
    
    /* datei2.c */
    #include "C.h"
    
    /* Wenn datei2.c kompoliert wird, weiß der Präprozessor nichts über frühere
    definierte Markos, usw. An der Stelle ist es genauso wie oben */
    

    ich hoffe, jetzt ist es verständlicher



  • camper schrieb:

    Allerdings erlaubt C (im Gegensatz zu C++ im Übrigen) kein Mehrfachdeklaration von Bezeichner ohne Linkage (also unter Anderem Typbezeichnern) mit Ausnahme von Tagnamen.

    warum macht c++ das anders? hast du ein beispiel?
    btw: hat nicht gerade die c++ community den buzzword-verdächtigen begriff 'one definition rule' erfunden?
    🙂


  • Mod

    odr-freak schrieb:

    camper schrieb:

    Allerdings erlaubt C (im Gegensatz zu C++ im Übrigen) kein Mehrfachdeklaration von Bezeichner ohne Linkage (also unter Anderem Typbezeichnern) mit Ausnahme von Tagnamen.

    warum macht c++ das anders? hast du ein beispiel?

    In C++ sind Tagnamen normale Typnamen, zudem werden Strukturen in C häufig so definiert

    typedef struct Foo { ... } Foo;
    

    In C bezeichnen die beiden Foo unterschiedliche Dinge, eines ist der Tagname, das andere ein normaler typedef-Name. In C++ soll dieser Code unverändert gültig sein, dass geht nur, wenn man die Redeklaration eines Typs per typedef auf den gleichen Typ zulässt, also Allgemein

    typedef Foo Foo;
    

    Das nun wiederum nicht mehrfach zu dürfen würde die Sache unnötig kompliziert machen, ein Nutzen in einer solchen Beschränkung wäre nicht ersichtlich. Der Versuch, den Namen per typedef für einen anderen Typen zu verwenden ist allerdings selbstverständlich ein Fehler.
    Man könnte es als Kuriosum betrachten, mehrfache typedefs sind in C++ erlaubt, um C-kompatibel zu bleiben, obwohl mehrfache typedefs in C verboten sind. 😉

    odr-freak schrieb:

    btw: hat nicht gerade die c++ community den buzzword-verdächtigen begriff 'one definition rule' erfunden?

    Das ist kein Begriff der Community sondern des Standards selbst. Die zugehörigen Regeln (es sind mehrere, immerhin 2 Seiten des Dokumentes) sind komplex genug, sie unter einem Begriff zusammenzufassen.



  • ^^merci. aus kompatibilitätsgründen, ich verstehe...
    würde denn folgendes in c++ gehen?

    struct Foo {...};
    ...
    Foo a;         // <-- so macht man's ja in c++, in c braeuchte man ein typedef
    struct Foo b;  // <-- C-style object. geht das auch in C++ wegen kompatibilität zu C?
    

    🙂



  • camper schrieb:

    Man könnte es als Kuriosum betrachten, mehrfache typedefs sind in C++ erlaubt, um C-kompatibel zu bleiben, obwohl mehrfache typedefs in C verboten sind. 😉

    c++ ist in der tat ein kuriosum, denn es soll ja bis zu einem gewissen grad C ähneln, aber nicht umgekehrt.
    🙂


  • Mod

    typedef-freak schrieb:

    struct Foo b;  // <-- C-style object. geht das auch in C++ wegen kompatibilität zu C?
    

    Ja. Manchmal muss man es sogar so machen: falls Foo als normaler Bezeichner noch für etwas Anderes verwendet wird. z.B.

    struct Foo { ... };
    void Foo();
    
    struct Foo b; // struct zwingend
    

    In C sowieso klar, in C++ befinden sich beide Namen im gleichen Namensraum, deshalb gibt es hier eine spezielle Verdeckungsregel. Der Name der Struktur wird verdeckt, und man brauch dann eben das Schlüsselwort struct, um doch noch auf die Struktur zugreifen zu können. Das ist allerdings wirklich ein reines Kompatibilitätsfeature.



  • danke nochmals. aber eine letzte frage habe ich noch: warum kann man in c++ das 'struct' eigentlich weglassen. z.b. bei...

    struct Foo {...};
    ...
    Foo a; // <- hier meine ich
    

    gibt es dafür einen vernünftigen grund? um einem frühzeitigen verschleiss der tastatur vorzubeugen, wird man es wohl kaum gemacht haben.
    🙂


  • Mod

    Foo-freak schrieb:

    danke nochmals. aber eine letzte frage habe ich noch: warum kann man in c++ das 'struct' eigentlich weglassen. z.b. bei...

    struct Foo {...};
    ...
    Foo a; // <- hier meine ich
    

    gibt es dafür einen vernünftigen grund? um einem frühzeitigen verschleiss der tastatur vorzubeugen, wird man es wohl kaum gemacht haben.
    🙂

    Hier müsste ich Vermutungen anstellen, möglich dass Stroustrup dazu etwas im D&E sagt - der class-key (struct/union/class bzw. analog enum) hat allerdings keinen semantischen Gehalt, ist also überflüssig für das Verständnis eines Algorithmus. Umgekehrt habe ich mich immer gefragt, wozu C Tag-namen benutzt. Schließlich wird man es - gerade in C - mit Stirnrunzeln betrachten, wenn der gleiche Bezeichner gleichzeitig verschiedene Dinge bezeichnen kann. Und wozu sonst sollten Tagnamen in einem anderen Namensraum liegen, wenn nicht um den Namen gleichzeitig für etwas Anderes (ein Objekt oder eine Funktion) benutzen zu können. Nicht zuletzt eignet sich ein konkreter Name in einem System üblicherweise nur für eine bestimmte Kategorie. Andererseits war C schon immer etwas mehr auf der kryptischen Seite der Macht...



  • camper schrieb:

    Umgekehrt habe ich mich immer gefragt, wozu C Tag-namen benutzt. Schließlich wird man es - gerade in C - mit Stirnrunzeln betrachten, wenn der gleiche Bezeichner gleichzeitig verschiedene Dinge bezeichnen kann. Und wozu sonst sollten Tagnamen in einem anderen Namensraum liegen, wenn nicht um den Namen gleichzeitig für etwas Anderes (ein Objekt oder eine Funktion) benutzen zu können.

    ich sehe da keinen widerpruch. die tag-namen für structs befinden sich im 'struct' namensraum, funktions- und variablen-bezeichner etc. befinden sich im 'object' namensraum, tag-namen für enums befinden sich im 'enum' namensraum, typedefs befinden sich ... usw.

    camper schrieb:

    Andererseits war C schon immer etwas mehr auf der kryptischen Seite der Macht...

    naja, ich glaube C ist für viele einsteiger schon recht kryptisch (ich würde auch nie einem programmieranfänger raten, mit C anzufangen), aber wenn man sich länger damit beschäftigt, ist die logik dahinter gar nicht so schwer zu durchschauen.

    btw, ich bin kein freund von c++. ich bin der meinung, daß c++ überflüssig ist, weil zwischen low-level (asm, c) und high-level (die meisten anderen programmiersprachen) keine lücke existiert, die c++ imstande wäre zu füllen.
    aber trotzdem, camper, entschuldige bitte diese etwas persönliche frage: du bist, meiner meinung nach, der ultimative c++ guru auf diesem board (kein scherz). woher kommt dein extremes wissen über diese sprache? entwickelst du selber c++ compiler oder sowas?
    🙂


  • Mod

    programminglanguage-freak schrieb:

    camper schrieb:

    Umgekehrt habe ich mich immer gefragt, wozu C Tag-namen benutzt. Schließlich wird man es - gerade in C - mit Stirnrunzeln betrachten, wenn der gleiche Bezeichner gleichzeitig verschiedene Dinge bezeichnen kann. Und wozu sonst sollten Tagnamen in einem anderen Namensraum liegen, wenn nicht um den Namen gleichzeitig für etwas Anderes (ein Objekt oder eine Funktion) benutzen zu können.

    ich sehe da keinen widerpruch. die tag-namen für structs befinden sich im 'struct' namensraum, funktions- und variablen-bezeichner etc. befinden sich im 'object' namensraum, tag-namen für enums befinden sich im 'enum' namensraum, typedefs befinden sich ... usw.

    Ich habe keine Probleme mit dem Mechanismus sondern mit dem warum des Ganzen. Warum beutzt du denn typedefs - wenn doch die Angabe von struct/enum etc. angeblich so wichtig ist? In meinen Augen wird die Angelegenheit durch die separaten Namensräume unnötig verkompliziert. Ich könnte mir vorstellen - das ist aber nichts als Spekulation - dass es ursprünglich (in einem sehr frühen C) kein typedef gab. In diesem Falle ergibt das Ganze tatsächlich einen Sinn: dann wird nämlich jede Typangabe durch ein entsprechendes Schlüsselwort (ein Grundtyp oder eben enum/struct) eingeleitet, entsprechend vereinfacht sich die Grammatik und in Konsequenz wird die Implementation simpler.

    programminglanguage-freak schrieb:

    woher kommt dein extremes wissen über diese sprache? entwickelst du selber c++ compiler oder sowas?

    So besonders viel weiß ich nicht. Ich vergesse allerdings in der Regel nichts, worüber ich schon mal diskutiert habe und ja, der Standard liegt jederzeit griffbereit und wird auch regelmäßig genutzt. Lesen, Verstehen, Nachdenken - nicht unbedingt in dieser Reihenfolge - mehr ist nicht dabei (die Dauer der Board-Mitgliedschaft entspricht ungefähr dem zeitlichen Rahmen). Es ist möglicherweise hilfreich, dass ich beruflich nicht mal entfernt etwas mit Programmierung zu tun habe.



  • @supertux

    Danke, mit deiner Methode geht es jetzt 🙂



  • camper schrieb:

    Warum beutzt du denn typedefs - wenn doch die Angabe von struct/enum etc. angeblich so wichtig ist? In meinen Augen wird die Angelegenheit durch die separaten Namensräume unnötig verkompliziert.

    das mache ich eher selten. und wenn, dann wirklich nur um schreibarbeit zu sparen. ich finde, es macht den code meistens lesbarer, wenn man den vollständigen typ hinschreibt und keine typedef-definitionen.

    programminglanguage-freak schrieb:

    Es ist möglicherweise hilfreich, dass ich beruflich nicht mal entfernt etwas mit Programmierung zu tun habe.

    damit könntest du allerdings recht haben.

    @ZzetT: sorry für's thread-hijacking.

    🙂



  • namespacing-freak schrieb:

    camper schrieb:

    Warum beutzt du denn typedefs - wenn doch die Angabe von struct/enum etc. angeblich so wichtig ist? In meinen Augen wird die Angelegenheit durch die separaten Namensräume unnötig verkompliziert.

    das mache ich eher selten. und wenn, dann wirklich nur um schreibarbeit zu sparen. ich finde, es macht den code meistens lesbarer, wenn man den vollständigen typ hinschreibt und keine typedef-definitionen.

    geht mir genauso. Ich verwendet typedef in den seltensten Fällen, außer wenn ich Funktionspointer an Funktionen übergeben muss, da ist ein typedef schon klasse.


Anmelden zum Antworten