Frage zu Headerfiles



  • Hallo 🙂

    Also ich habe sein einiger Zeit wieder angefangen mit C++ und mir ist aufgefallen, dass ja solche "Grundfunktionen" wie "cout" ja auch irgendwo definiert sein müssen. Daraufhin habe ich mir <iostream> etwas genauer angeschaut und habe das hier gefunden:

    _STD_BEGIN
    
      #ifdef _M_CEE_PURE
    __PURE_APPDOMAIN_GLOBAL extern istream cin, *_Ptr_cin;
    __PURE_APPDOMAIN_GLOBAL extern ostream cout, *_Ptr_cout;
    __PURE_APPDOMAIN_GLOBAL extern ostream cerr, *_Ptr_cerr;
    __PURE_APPDOMAIN_GLOBAL extern ostream clog, *_Ptr_clog;
    
    __PURE_APPDOMAIN_GLOBAL extern wistream wcin, *_Ptr_wcin;
    __PURE_APPDOMAIN_GLOBAL extern wostream wcout, *_Ptr_wcout;
    __PURE_APPDOMAIN_GLOBAL extern wostream wcerr, *_Ptr_wcerr;
    __PURE_APPDOMAIN_GLOBAL extern wostream wclog, *_Ptr_wclog;
    
      #else /* _M_CEE_PURE */
    		// OBJECTS
    __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 istream cin, *_Ptr_cin;
    __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 ostream cout, *_Ptr_cout;
    __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 ostream cerr, *_Ptr_cerr;
    __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 ostream clog, *_Ptr_clog;
    
    __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 wistream wcin, *_Ptr_wcin;
    __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 wostream wcout, *_Ptr_wcout;
    __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 wostream wcerr, *_Ptr_wcerr;
    __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 wostream wclog, *_Ptr_wclog;
    
    		// CLASS _Winit
    
      #endif
    _STD_END
    

    Jetzt meine Frage: Ist das denn noch C++? Wenn nicht, was dann? Es muss doch etwas ziemlich systemnahes sein wenn es die Grundfunktion für Textausgabe definiert, oder? Wenn jemand weiß was der Code beudeut wärs nett wenn ihr mir das erläutern könntet 😃

    Ich bin dankbar für alle Antworten 😉
    mfg



  • int main() schrieb:

    Jetzt meine Frage: Ist das denn noch C++?

    Ja. Abgesehen von den Makros und etwas speziellen Bezeichnern sehe ich hier nichts Aussergewöhnliches. Gut, die Deklaration von Objekt und Zeiger in einer Zeile ist zwar hässlich, aber durchaus erlaubt...



  • <iostream> gehört zum "Gesamtpaket", welches ein Compiler-Hersteller bereitstellt. Im C++ Standard ist nicht mal festgelegt, dass <iostream> wirklich eine Datei sein muss. Es ist nur festgelegt, dass, wenn du "#include <iostream>" schreibst, bestimmte Dinge benutzbar sein müssen. Wie das im Endeffekt implementiert wird, hat den Programmierer eigentlich nicht zu interessieren.

    int main() schrieb:

    Jetzt meine Frage: Ist das denn noch C++?

    Möglicherweise ja, möglicherweise nein.

    int main() schrieb:

    Wenn nicht, was dann?

    Irgendetwas Compiler-spezifisches eventuell. Der Hersteller darf natürlich Dinge im Compiler einbauen, die über C++ hinausgehen und welche in den "Standard-Headern" verwendet werden können. Beispielsweise wird C++0x ein paar type traits anbieten, die man in "reinem C++" gar nicht implementieren kann. Das heißt, der Compilerhersteller muss Extra-Sprach-Features einbauen, um die type traits implementieren zu können. Das beschreibt man typischerweise mit "Compiler-Magie".



  • krümelkacker schrieb:

    <iostream> gehört zum "Gesamtpaket", welches ein Compiler-Hersteller bereitstellt. Im C++ Standard ist nicht mal festgelegt, dass <iostream> wirklich eine Datei sein muss. Es ist nur festgelegt, dass, wenn du "#include <iostream>" schreibst, bestimmte Dinge benutzbar sein müssen. Wie das im Endeffekt implementiert wird, hat den Programmierer eigentlich nicht zu interessieren.

    Stimmt so nicht. <iostream> gehört zur Standardbibliothek - und die hat nichts mit dem Compiler zu tun. Bei einem standardkonformen Compiler kann die Implementierung der Standardbibliothek (wozu auch, bzw. dank diverser Templates grade die Header gehören) gegen eine andere ausgetauscht werden, ohne dass es den Compiler schmerzt.
    Daraus folgt dann auch, dass #include <iostream> tatsächlich einen Header einbindet. Der allerdings wie hier im MSVC-Fall durchaus Compilerspezifische Elemente beinhalten kann.



  • Der Code beschreibt eigentlich nur, dass in irgendeiner Datei der Standardlibrary die Variablen cin, cout, cerr, clog, wcin, wcout, wcerr und wclog sowie die ganzen Pointer darauf angelegt sind und später zum Programm dazugelinkt werden. Was darin passiert, hat mit diesem Header erstmal nichts zu tun.



  • pumuckl schrieb:

    Stimmt so nicht. <iostream> gehört zur Standardbibliothek - und die hat nichts mit dem Compiler zu tun. Bei einem standardkonformen Compiler kann die Implementierung der Standardbibliothek (wozu auch, bzw. dank diverser Templates grade die Header gehören) gegen eine andere ausgetauscht werden, ohne dass es den Compiler schmerzt.
    Daraus folgt dann auch, dass #include <iostream> tatsächlich einen Header einbindet. Der allerdings wie hier im MSVC-Fall durchaus Compilerspezifische Elemente beinhalten kann.

    Es muß keine Datei sein, damit ich es austauschen kann.

    Namespaces sind offen, und somit kann ich auch einfach einen anderen Header inkludieren, ohne Programmcode ändern zu müssen. Gerade das ist der Vorteil von der Offenheit der Namespaces:

    #include <my_iostream> // inkludiert selber kein <iostream>, stellt aber ein eigenes std::cout bereit
    
    int main()
    {
       std::cout << "Hallo";
    }
    

    Insofern müssen für die Fälle Std-Header keine Dateien sein.

    Hat den Vorteil, das ich beide Header verwenden kann. In deinem Beispiel müsste ich auf den originalen Std-Header verzichten, was meiner Meinung nach inakzeptabel ist!



  • pumuckl schrieb:

    krümelkacker schrieb:

    <iostream> gehört zum "Gesamtpaket", welches ein Compiler-Hersteller bereitstellt. Im C++ Standard ist nicht mal festgelegt, dass <iostream> wirklich eine Datei sein muss. Es ist nur festgelegt, dass, wenn du "#include <iostream>" schreibst, bestimmte Dinge benutzbar sein müssen. Wie das im Endeffekt implementiert wird, hat den Programmierer eigentlich nicht zu interessieren.

    Stimmt so nicht. <iostream> gehört zur Standardbibliothek - und die hat nichts mit dem Compiler zu tun.

    Bei einem standardkonformen Compiler kann die Implementierung der Standardbibliothek (wozu auch, bzw. dank diverser Templates grade die Header gehören) gegen eine andere ausgetauscht werden, ohne dass es den Compiler schmerzt.

    Dass <iostream> zur Standardbibliothek gehört heißt nicht, dass es eine Datei Namens iostream irgendwo geben muss. So oder in ähnlicher Form hat es auch eine C++ Autorität formuliert (Stroustrup, Sutters oder Meyers). Sorry, hab grad keine Referenz zur Hand. Ich verlasse mich da im Augenblick auf mein Gedächtnis. Mir ist auch diese Garantie, von der Du sprichst (dass die stdlib ersetzbar sein muss), nicht geläufig. Ich tippe eher darauf, dass Du Dir diese Garantie selbst ausgehend von einer Dir vertrauten Implementierung zusammen gereimt hast. Ich lass mich aber gerne eines besseren belehren (Zitate aus dem Standard sind willkommen).

    kk



  • Der Standard spricht eigentlich nicht von Compilern und Libraries, sondern nur allgemein von der Implementierung. Ich bin mir ziemlich sicher, dass er nirgeds garantiert oder auch nur andeutet, dass man die Standardbibliothek austauschen können muss. Das geht schon allein deshalb nicht, weil die Standardbibliothek nicht vollständig in Standard-C++ implementiert werden kann. Es müsste also eine Kern-API geben, auf die dann eine in Standard-C++ geschriebene, austauschbare Standardbibliothek aufsetzen kann. Aber die gibt es nicht.


  • Mod

    Der Standard garantiert, dass die Standardbibliothek (also die Deklarationen) als "Header" vorliegt. Eine Fußnote weist aber ausdrücklich darauf hin, dass mit "Header" etwas gemeint ist, was mit #include<...> eingebunden werden kann, aber nicht zwangsläufig eine Datei sein muss. Im Gegensatz zu #include"...", welches nur Dateien einbindet. Falls dieser Fall vorliegt und man seine eigene Datei mit dem Namen des Headers bereitstellt, ist das Verhalten undefiniert.

    Alles Kapitel 17.

    Ich muss zugeben: Hat mich jetzt etwas überrascht.



  • Artchi schrieb:

    Namespaces sind offen

    Mit Ausnahme des namespace std (§17.4.3.1)

    SeppJ schrieb:

    Der Standard garantiert, dass die Standardbibliothek (also die Deklarationen) als "Header" vorliegt. Eine Fußnote weist aber ausdrücklich darauf hin, dass mit "Header" etwas gemeint ist, was mit #include<...> eingebunden werden kann, aber nicht zwangsläufig eine Datei sein muss. Im Gegensatz zu #include"...", welches nur Dateien einbindet. Falls dieser Fall vorliegt und man seine eigene Datei mit dem Namen des Headers bereitstellt, ist das Verhalten undefiniert.

    Alles Kapitel 17.

    Ich muss zugeben: Hat mich jetzt etwas überrascht.

    Okay, mich auch. Ich muss gestehen dass bei mir auch der Gedächtnis-ohne-Referenzen-Fall vorlag bzgl. Austauschbarkeit der Bibliotheken.
    vgl. auch §16.2,2 bzgl. Header-inclusion vs. Sourcefile-inclusion

    Wobei ich aber bleibe:
    Die Implementierung der Standardbibliothek hat nicht zwangsläufig mit dem Compiler zu tun. Lediglich die Orte, wo die Definitionen und Deklarationen zu finden sind, sind Compilerabhängig. Das folgt auch aus Kap. 17 sowie 16.2,2: Die Header-includes sorgen nach 16.2,2 dafür, dass an der Stelle der inlcude-Direktive der Inhalt des Headers in die Übersetzungseinheit eingefügt wird. Und wie auch immer der Header aussieht und wo er liegt, muss sein Inhalt dementsprechend standardkonformes C++ sein (Modulo Extensions wie im MSVC-Fall).

    Bashar schrieb:

    Der Standard spricht eigentlich nicht von Compilern und Libraries, sondern nur allgemein von der Implementierung.

    Der Standard spricht sehr wohl an einigen Stellen von der Library (manchmal auch der standard library) und der library implementation. Allerdings wird mehr oder weniger implizit davon ausgegangen, dass diese library (und damit auch ihre implementation) Teil der "implementation" ist.

    Bashar schrieb:

    Das geht schon allein deshalb nicht, weil die Standardbibliothek nicht vollständig in Standard-C++ implementiert werden kann. Es müsste also eine Kern-API geben, auf die dann eine in Standard-C++ geschriebene, austauschbare Standardbibliothek aufsetzen kann. Aber die gibt es nicht.

    Die Header-Inhalte müssen wie gesagt in C++ vorliegen. Sie dürfen andere Header einbinden und auf Funktionen zugreifen, die nicht in der library sind.
    Da jedoch alles in der library externe linkage hat, können die eigentlichen Funktionen in anderen Sprachen implementiert werden.

    Einem Compiler, der einen Austausch der Standardbibliotheksimplementierung erlaubt, müsste daher folgende mitgeteilt werden können:
    - Ort und Aufbau der Library Header
    - Wie die in der Bibliothek definierten Objekte und Funktionen vor Programmstart (⚠) in das Programm eingebunden werden.

    ⚠ Nach 17.4.2.2,3 müssen die Inhalte der Standardbibliothek nicht zur Linkzeit mit ins Programm gelinkt werden.



  • pumuckl schrieb:

    [...] Und wie auch immer der Header aussieht und wo er liegt, muss sein Inhalt dementsprechend standardkonformes C++ sein (Modulo Extensions wie im MSVC-Fall).

    Komische Schlussfolgerung ... sieht ein bischen nach einer Tautologie à la "Der Teil, der standardkonform ist, ist standardkonform" aus.



  • krümelkacker schrieb:

    pumuckl schrieb:

    [...]

    Komische Schlussfolgerung ... sieht ein bischen nach einer Tautologie à la "Der Teil, der standardkonform ist, ist standardkonform" aus.

    Sollte bloß verdeutlichen, dass auch wenn ein Header keine eigene Sourcefile sein muss, der Inhalt dennoch C++-Code ist und an der entsprechenden Stelle eingefügt wird und nicht ein #include <iostream> durch irgendwelche Compilermagie dazu führt, dass der plötzlich einfach "weiß" was cin, cout & Co sind.



  • pumuckl schrieb:

    [...] der Inhalt dennoch C++-Code ist und an der entsprechenden Stelle eingefügt wird und nicht ein #include <iostream> durch irgendwelche Compilermagie dazu führt, dass der plötzlich einfach "weiß" was cin, cout & Co sind.

    Das kannst Du gar nicht verbieten, da es nach der as-if-Regel eigentlich erlaubt sein sollte.



  • krümelkacker schrieb:

    pumuckl schrieb:

    [...] der Inhalt dennoch C++-Code ist und an der entsprechenden Stelle eingefügt wird und nicht ein #include <iostream> durch irgendwelche Compilermagie dazu führt, dass der plötzlich einfach "weiß" was cin, cout & Co sind.

    Das kannst Du gar nicht verbieten, da es nach der as-if-Regel eigentlich erlaubt sein sollte.

    In den betreffenden Sätzen gibts keine as-if-Regeln:

    §16.2,2 schrieb:

    A preprocessing directive of the form
    # include <h-char-sequence> new-line
    [...], and causes the replacement of that directive by the entire contents of the header.[...]

    §17.4.2.1,1 schrieb:

    The entities in the C++ Standard Library are defined in headers, whose contents are made available to a translation unit when it contains the appropiate #include preprocessing directive (16.2)



  • 17.4.1.2§1:

    The elements of the C++ Standard Library are declared or defined (as appropriate) in a header.158)

    Mit der Fußnote 158):

    A header is not necessarily a source file, nor are the sequences delimited by < and > in header names necessarily valid source file names.


  • Mod

    Letztlich hängt es an der Interpretation von "are made available to a translation unit". Ich würde nicht sagen, dass dies zwangsläufig das Einfügen von Text bedeuten muss.



  • pumuckl schrieb:

    krümelkacker schrieb:

    pumuckl schrieb:

    [...]

    Komische Schlussfolgerung ... sieht ein bischen nach einer Tautologie à la "Der Teil, der standardkonform ist, ist standardkonform" aus.

    Sollte bloß verdeutlichen, dass auch wenn ein Header keine eigene Sourcefile sein muss, der Inhalt dennoch C++-Code ist und an der entsprechenden Stelle eingefügt wird und nicht ein #include <iostream> durch irgendwelche Compilermagie dazu führt, dass der plötzlich einfach "weiß" was cin, cout & Co sind.

    Naja, ... der Teil mit den "Extensions" führt den Rest etwas ad absurdum 🙂

    Wenn ich nen Compiler schreibe, dann kann ich z.B. einfach ein File namens "iostream" mit folgendem Inhalt ausliefern

    #pragma standard_header("iostream")
    

    Der Include-Mechanismus ist dann völlig standardkonform implementiert, cin/cout etc. werden aber trotzdem über "Compilermagie" definiert.



  • SeppJ schrieb:

    Letztlich hängt es an der Interpretation von "are made available to a translation unit". Ich würde nicht sagen, dass dies zwangsläufig das Einfügen von Text bedeuten muss.

    Der Teil den du zitierst nicht. 16.2,2 "causes the replacement of that directive by the entire contents of the header" besagt aber genau das.

    @Bashar: wie oben beschrieben

    pumuckl schrieb:

    dass auch wenn ein Header keine eigene Sourcefile sein muss,

    , das steht in besagter Fußnote.

    pumuckl schrieb:

    der Inhalt dennoch C++-Code ist und an der entsprechenden Stelle eingefügt wird

    Steht in 16.2,2

    Die Fußnote besagt nur, dass es keine source-file sein muss. Sie besagt nicht, dass ein header keinen Sourcecode enthalten braucht. IMO bedeutet die Fußnote nur, dass z.B. ein header ein Feld in einer Datenbank sein kann oder ein Abschnitt einer wie auch immer kodierten Datei (aber eben keine eigene Datei mit Namen iostream). Der Inhalt (content) eines Headers muss aber compilierbarer Code sein, da dieser laut 16.2,2 in Phase 4 an Stelle der include-Direktive in den Sourcecode der ÜE eingesetzt wird.


Anmelden zum Antworten