Allg. Frage zu .h-Dateien



  • Nachdem ich in meinen Quellcode "#include <stdio>" geschrieben habe kann ich z.B die Funktion printf benutzen.

    Wie geht das denn, wenn man in Header-Dateien gar keine Funktionen implementieren (richtiges Wort?) darf.
    Ich hab mir die Datei angekuckt und da ist die Funktion als "_CRTIMP" deklariert.

    2. Frage: Wie geht man denn generell mit Modularisierung um?
    Heißt das z.B, dass ich die Funktionen in .c Dateien mache, für jede dieser .c Dateien eine .h Datei mit allen Typendefinitionen mache, in jeder .c Datei die eigene .h Datei und die benötigten .c Dateien includiere und ich per ifndef etc. sicherstelle, dass keine der .c Dateien doppelt includiert wird.

    Wahrscheinlich nicht. Aber wie sonst?



  • obbba schrieb:

    Nachdem ich in meinen Quellcode "#include <stdio>" geschrieben habe kann ich z.B die Funktion printf benutzen.

    Das glaube ich weniger.

    obbba schrieb:

    Wie geht das denn, wenn man in Header-Dateien gar keine Funktionen implementieren (richtiges Wort?) darf.

    Die Implementierung ist bereits compiliert und wird nur noch zu deinem Programm gelinkt.

    obbba schrieb:

    Ich hab mir die Datei angekuckt und da ist die Funktion als "_CRTIMP" deklariert.

    Uninteressant, _CRTIMP ist sicher selber ein DEFINE oder so ein Kram. Entscheident ist nicht WIE der Standard implementiert ist, sondern, DASS er es ist und sich auch so verhaelt. Der Header sieht in einer anderen Implementierung der Standardlib ganz anderst aus.

    obbba schrieb:

    Wahrscheinlich nicht.

    Nein.



  • stdio.h

    Entenwickler schrieb:

    obbba schrieb:

    "]Wahrscheinlich nicht.

    Nein.

    Also was?



  • obbba schrieb:

    2. Frage: Wie geht man denn generell mit Modularisierung um?
    Heißt das z.B, dass ich die Funktionen in .c Dateien mache, für jede dieser .c Dateien eine .h Datei mit allen Typendefinitionen mache, in jeder .c Datei die eigene .h Datei und die benötigten .c Dateien includiere und ich per ifndef etc. sicherstelle, dass keine der .c Dateien doppelt includiert wird.

    in .h dateien gehört grundsätzlich nix rein, was compiliert wird (im sinne von asm/obj-codeerzeugung), sondern nur definitionen, konstanten, funktionsprototypen, definitionen von strukturen etc.
    in die .c dateien kommen dann die konkreten implementierungen (funktionen, globale und static variablen usw.), also alles was 'code' erzeugt und den rom/ram/flash/whatever-speicher füllt.
    verbindungen stellste für den compiler her, indem du im .c-file die passenden .h-files #includest, so dass der compiler 'weiss' wie die funktionen, strukturen, konstanten etc. für die anderen c-files definiert sind, so dass du von dort die externen funktionen aufrufen kannst, ohne compiler-fehler und -warnings zu bekommen.
    benutz du eine toolchain, die erstmal alle c-files in assemblercode umwandelt, dann wird jetzt assembliert d.h. der assembler übersetzt die vom c-compiler erzeugten .asm-files in object-files für den linker. an dieser stelle werden auch alle selbstgeschrieben .asm-files, die zum projekt gehören, mit übersetzt.
    zum schluss kommen linker/locator dran, der/die alle object-files, den startup-code, libraries (vorcompilierte object-files, die z.b. standard funktionen wie 'strlen' enthalten) zu einem ausführbaren programm machen...
    :xmas2:
    ausnahmen bestätigen die regel 😉



  • 👍



  • ten schrieb:

    in .h dateien gehört grundsätzlich nix rein, was compiliert wird (im sinne von asm/obj-codeerzeugung), sondern nur definitionen, konstanten, funktionsprototypen, definitionen von strukturen etc.

    Extrem kleine und kurze Funktionen kann man direkt im Header implementieren dass der Compiler sie inlinen kann. In C gibts noch die Alternative des Defines, aber das finde ich irgendwie grottig - villeicht weil ich von C++ komme.



  • Entenwickler schrieb:

    ten schrieb:

    in .h dateien gehört grundsätzlich nix rein, was compiliert wird (im sinne von asm/obj-codeerzeugung), sondern nur definitionen, konstanten, funktionsprototypen, definitionen von strukturen etc.

    Extrem kleine und kurze Funktionen kann man direkt im Header implementieren dass der Compiler sie inlinen kann. In C gibts noch die Alternative des Defines, aber das finde ich irgendwie grottig - villeicht weil ich von C++ komme.

    Ahso, in c++ - Headerdateien gibts also keine defines. Gibts zwei verschiedene
    c++-Sprachen? 😕



  • Entenwickler schrieb:

    Extrem kleine und kurze Funktionen kann man direkt im Header implementieren dass der Compiler sie inlinen kann.

    dafür braucht's ab ein non-standard keyword wie '__forceinline' oder so, sonst wird da doch 'ne funktion draus und wenn man dann die .h in mehr als ein .c-file includet gibts probleme beim linken 😉

    Entenwickler schrieb:

    In C gibts noch die Alternative des Defines, aber das finde ich irgendwie grottig

    das ist aber die einzige möglichkeit um wirklich was zu 'inlinen'. kann sich der compiler nicht gegen wehren...

    Entenwickler schrieb:

    - villeicht weil ich von C++ komme.

    naja, das ist sowieso die schlimmste fricklersprache, damit sind bestimmt viele unlogische faxen möglich...
    :xmas2:



  • In header dateien schreibt man ja immer (soweit ich weiß):
    z.B. bei meinheader.h

    #ifndef mein_header
    #define mein_header
    
    //... bla
    
    #endif
    

    ,damit man verhindert, dass ein header mehrmals includiert (richtiges Wort?) wird.

    Aber das gleiche kann mir doch auch mit normalen includierten .c oder .cpp Dateien passieren.
    Definiert man da auch für jede Datei eine Konstante?



  • ten schrieb:

    Entenwickler schrieb:

    Extrem kleine und kurze Funktionen kann man direkt im Header implementieren dass der Compiler sie inlinen kann.

    dafür braucht's ab ein non-standard keyword wie '__forceinline' oder so, sonst wird da doch 'ne funktion draus und wenn man dann die .h in mehr als ein .c-file includet gibts probleme beim linken 😉

    ne, das Keyword heißt inline und das ist ziemlich Standard, sowohl in C++, als auch C.



  • Ich glaube das kennt er schon. Und nein, ein __forceinline wäre nicht dasselbe wie ein inline. Aber das weisst du auch 😉



  • rüdiger schrieb:

    ten schrieb:

    Entenwickler schrieb:

    Extrem kleine und kurze Funktionen kann man direkt im Header implementieren dass der Compiler sie inlinen kann.

    dafür braucht's ab ein non-standard keyword wie '__forceinline' oder so, sonst wird da doch 'ne funktion draus und wenn man dann die .h in mehr als ein .c-file includet gibts probleme beim linken 😉

    ne, das Keyword heißt inline und das ist ziemlich Standard, sowohl in C++, als auch C.

    ich dachte immer, ein C-compiler kann 'inline' auch missachten 😕



  • obbba schrieb:

    Aber das gleiche kann mir doch auch mit normalen includierten .c oder .cpp Dateien passieren.
    Definiert man da auch für jede Datei eine Konstante?

    .c und .cpp-Dateien inkludiert man nicht!

    @net
    und __forceinline kann der Compiler vermutlich auch ignorieren

    (sonst wäre

    __forceinline void f() {
      f();
    }
    

    sehr spaßig ;))

    aber sagen wir mal in 99% der Fälle hat das ja einen Sinn, wenn der Compiler ein inline ignoriert.



  • rüdiger schrieb:

    @net
    und __forceinline kann der Compiler vermutlich auch ignorieren

    (sonst wäre

    __forceinline void f() {
      f();
    }
    

    sehr spaßig ;))

    Compilerfehler.

    rüdiger schrieb:

    aber sagen wir mal in 99% der Fälle hat das ja einen Sinn, wenn der Compiler ein inline ignoriert.

    Ich finde die 99% zwar zu hoch gegriffen, aber es ändert nichts an der Sache, dass ein "echtes" inline, also ein __forceinline, schon manchmal sinnvoll wäre. Mein Compiler kennt leider nichtmal inline und selbst wenn, würde es mir nicht viel bringen wenn ich mich nicht darauf verlassen kann.



  • rüdiger schrieb:

    obbba schrieb:

    Aber das gleiche kann mir doch auch mit normalen includierten .c oder .cpp Dateien passieren.
    Definiert man da auch für jede Datei eine Konstante?

    .c und .cpp-Dateien inkludiert man nicht!

    Heißt das, dass alle Funtionen in eine Datei kommen?
    Aber die machen doch gerade den meisten Text aus!
    (Allerdings muss man dann nicht so oft andere Dateien öffnen
    - aber auch mehr scrollen)

    Das würde mein Weltbild komplett umwerfen. 😮
    Ich hatte doch irgendwo mal gehört, dass man den Code in mehrere Dateien aufspalten sollte sobald er ungefähr die Größe eines DIN-A4-Blattes hat.

    //edit:
    Ich wette man teilt den Code trotzdem auf und setzt ihn dann mit Hilfe von diesen Makefiles wieder zusammen.
    Und was soll ich, als verwöhnter Dev-C++ Benutzer, bei dem die Makefiles automatisch erstellt werden, machen?



  • rüdiger schrieb:

    aber sagen wir mal in 99% der Fälle hat das ja einen Sinn, wenn der Compiler ein inline ignoriert.

    aber sagen wir mal: in 99.2% aller fälle hat es einen sinn, wenn der coder ein 'inline' hinschreibt 😉

    TactX schrieb:

    Ich finde die 99% zwar zu hoch gegriffen, aber es ändert nichts an der Sache, dass ein "echtes" inline, also ein __forceinline, schon manchmal sinnvoll wäre. Mein Compiler kennt leider nichtmal inline und selbst wenn, würde es mir nicht viel bringen wenn ich mich nicht darauf verlassen kann.

    das ist der punkt. ich verwende 'inline' nie, weil's absoluter quatsch ist. wenn ich z.b. gewisse optimierungen einschalte (optimize for speed o.ä.), dann inlined mein compiler sowieso automatisch die funktionen, von denen er meint, inlining würde die ausführung des codes beschleunigen.
    wenn ich der meinung bin, schlauer zu sein als mein compiler, dann verwende ich nonstandard-erweiterungen, die inlining erzwingen. soll der code portabel sein, dann müssen eben makros her.
    :xmas2:



  • obbba schrieb:

    rüdiger schrieb:

    obbba schrieb:

    Aber das gleiche kann mir doch auch mit normalen includierten .c oder .cpp Dateien passieren.
    Definiert man da auch für jede Datei eine Konstante?

    .c und .cpp-Dateien inkludiert man nicht!

    Heißt das, dass alle Funtionen in eine Datei kommen?

    Nein, da hast du dich wohl undeutlich ausgedrückt. Ich dachte du meintest mit "inkludieren" -> "Benutzung von #include".



  • Hat jmd viell einen link wo die Modularisierung (bis ins detail also headers schreiben etc) beschrieben wird?

    Würd ich mir sehr gern aneignen, in meinen Büchern wirds leider ned beschrieben.

    MFG



  • rüdiger schrieb:

    Nein, da hast du dich wohl undeutlich ausgedrückt. Ich dachte du meintest mit "inkludieren" -> "Benutzung von #include".

    Genau das hatte ich ja gedacht! Also macht man das mit makefiles. 💡
    Wenn ich bei der Dev-C++-IDE auf das weiße Blatt oben links und dann auf "neue Datei zum Projekt hinzufügen" klicke, wird die entsprechende Objekt-Datei dann automatisch zum Programm gelinkt?
    //Tatsächlich. Es funktioniert... Das ist aber toll...

    Dass das in Büchern (also in den 2,3 Büchern die ich kenne und in den Internet Tuts) nicht beschrieben wird, stimmt leider.



  • obbba schrieb:

    Heißt das, dass alle Funtionen in eine Datei kommen?
    Aber die machen doch gerade den meisten Text aus!
    (Allerdings muss man dann nicht so oft andere Dateien öffnen
    - aber auch mehr scrollen)

    nein, es ist natürlich möglich alles in einer einzigen Datei zu schreiben, aber wir sind Menschen, keine Compiler, mach das und siehe wie du dein Leben unnötig schwerer machst.

    obbba schrieb:

    Ich hatte doch irgendwo mal gehört, dass man den Code in mehrere Dateien aufspalten sollte sobald er ungefähr die Größe eines DIN-A4-Blattes hat.

    Das kannst du als eine Konvention für deine Projekte benutzen, ist aber allgemein nicht bekannt. Das Aufspalten dient eher dem Programmierer, damit er den Überblick über den Code nicht verliert. Wie gesagt, wir sind keine Compiler, wir müssen den Überblick behalten und damit spaltet man auch den Code auf. Ausserdem macht es Sinn, den Code in "Modulen" aufzuspalten, sprich Code zusammenzufassen (in eine Datei), der zusammen gehört. Das erhört den Überblick, vermeidet man schneller Fehler und ist vor allem beim Debuggen effizienter, weil man die Fehlerquelle besser eingrenzen kann.. Ich habe schon mal Code gesehen, wo einige Dateien kaum 3 KB groß waren und andere (im selben Projekt) größer als 250KB waren.

    obbba schrieb:

    Ich wette man teilt den Code trotzdem auf und setzt ihn dann mit Hilfe von diesen Makefiles wieder zusammen.

    Die Makefile sind dazu da, das Compilieren zu übernehmen (hat nichts dem Zusammensetzen von Dateien oder ähnliches). Niemand sagt, du sollst den Code in Datein aufspalten. Wenn du alles in einer Datei haben willst, dann tue dies, ist aber meiner Meinung nach kontraproduktiv. Dem Compiler ist aber egal, wie groß eine Datei ist.



  • Gut Danke. Schön ausführlich.


Anmelden zum Antworten