Modulares Programmieren



  • Hallo,

    ich versuche gerade eine Beschreibung über die Aufteilung eines Programms in mehrere Dateien zu finden, komme aber nicht weiter.

    wie funktioniert das mit der header datei usw. und was für eine rolle spielt das ifndef und endif usw.

    MfG



  • In den Header kommen Sachen, die du eventuell in mehreren .c-Dateien einbinden willst bzw. auch einfach zur Übersicht irgendwelche Typen-Definitionen, define-Makros, Funktionsprototypen usw. Mit #ifndef, #define und #endif erzeugt man sogenannte Include-Guards, die dafür sorgen, dass eine Header-Datei nicht doppelt eingebunden wird (sonst hättest du ja massenhaft 'already defined' Fehler). Das geht z.B. so:

    #ifndef MY_HEADER
    #define MY_HEADER
    
    //Inhalt deines Headers...
    
    #endif
    

    Beim ersten Versuch, diesen Header über #include einzubinden, ist MY_HEADER noch nicht definiert. Die Bedingung trifft also zu, die Konstante wird definiert und der Inhalt bis zum #endif wird eingebunden. Beim zweiten Versuch trifft dies nicht mehr zu und du verhinderst das doppelte inkludieren.

    Eine simplere Möglichkeit ist übrigens die Anweisung "#pragma once". Hier wird der gleiche Zweck erfüllt, du kannst halt nur nicht mehr abfragen, ob deine Präprozessor-Konstante existiert oder nicht.



  • Hallo matze,

    danke für deine Antwort.

    in meine main Datei muss ich alle Header Dateien einfügen.

    #include "funktion.h" 
    #include "funktion_2.h"
    
    1. Muss ich in die main Datei auch die anderen C-Dateien ,zb. funktion.c, einfügen.

    2. Brauche ich für jedes c-Unterprogramm eine eigene Header-Datei oder verbinde ich alle C-Programme mit nur einer Header-Datei.

    3. In die C-Datei "Funktion" schreibe ich mein Programm. Brauche ich da auch das include oder define usw. oder kommt das von der main-Datei.

    4. In die Header-Datei kommt die erste Zeile der Funktion und zb.

    #define zahl 10
    

    usw.

    Mir ist klar was das Ziel dieser Zeilen ist. Aber was genau sagt das ifndef aus und und was das define.

    #ifndef MY_HEADER
    #define MY_HEADER
    
    //Inhalt deines Headers...
    
    #endif
    
    1. Was meinst du mit:

    Beim zweiten Versuch trifft dies nicht mehr zu und du verhinderst das doppelte inkludieren.

    Wenn mein Programm kompiliert wird, dann steht die

    #include "funkiton.h"
    

    -Zeile nur einmal im Programm wieso sollte es einen zweiten Versuch geben das zu inkludieren

    Danke

    MfG



    1. Nein! Inkludiere bitte keine .c-Dateien. Das geht zwar theoretisch, macht aber gar keinen Sinn. Die .c-Dateien werden kompiliert (zu Objektdateien) und vom Linker zusammengefügt. Du musst sie in deiner IDE (z.B. Visual Studio) nur zu deinem Projekt hinzufügen, mehr nicht.

    2. Meistens hat man pro .c-Datei einen Header. Überlege dir Folgendes: du definierst eine Funktion in einer .c-Datei. Diese Funktion willst du aber auch in anderen Dateien nutzen. Dort ist sie nicht bekannt. Deshalb schreibst du den Funktionsprototypen in den zugehörigen Header. Den kannst du dann in anderen .c-Dateien einbinden und somit die Funktion bekannt machen, so dass du sie dort aufrufen kannst. Du kannst aber auch Header haben, die keiner .c-Datei zugehörig sind. Beispielsweise kannst du ja auch in einem Header komplette Funktionen (also nicht nur die Prototypen) unterbringen, oder auch Präprozessor-Konstanten und -Makros, die du überall gebrauchen kannst (z.B. #define PI=3.14...).

    3. Tut mir leid, verstehe ich nicht ganz.

    4. Du musst dir eines klarmachen: #define ist nur eine Textersetzung! Wenn du Folgendes eingibst

    #define PI 3.14
    

    ,dann wird an JEDE Stelle Code, an der du PI eingibst, "3.14" gesetzt, bevor kompiliert wird (deshalb Präprozessor). Genauso kannst du Makros definieren:

    ROUNDINT(x) ((x*10+5)/10)  //rundet auf Ganzzahlen
    

    Wenn du nun irgendwo im Code "ROUNDINT(3.4)" schreibst, dann wird diese Stelle durch "((3.4*10+5)/10)" ersetzt.

    1. Ganz kurz zu Include-Guards:

    Du sagst mit den Anweisungen: Wenn MY_HEADER nicht definiert ist (existiert), dann definiere MY_HEADER und "blende den Code bis #endif ein". Beim zweiten Versuch (#include-Anweisung) ist MY_HEADER bereits definiert und der ganze Code wird quasi "ausgeblendet" (Stichwort Textersetzung).
    Stell dir vor, du hast einen Header mit allgemeinen Definitionen (Shared.h), wie z.B. dem Runden-Makro von oben. Das brauchst du in vielen Dateien, so dass du eventuell in einer .c-Datei mehrere Header einbindest, die ihrerseits diesen allgemeinen Header einbinden. Wenn das doppelte Einbinden nicht verhindert wird, bekommst du 'ne Menge Compiler-Fehler wegen doppelten Bezeichnern. Probier es aus! Versuche, deinen Header zweimal hintereinander zu inkludieren. Ohne Include-Guard (bzw. #pragma once) bekommst du ein Problem...



  • Ich hätte auch eine Frage zu #ifdef.

    Ich habe also eine header-Datei Namens header_by_me mit:

    #ifdef SONDERDATENTYP
    define wchar char
    #endif
    

    Jetzt bin ich in meinen .c-Dateien.

    Wie genau mach ich dem Compiler klar, dass zB. in "Funktion_char.c" char für 16-Bit-char steht und in "Funktion_wchar.c" char für wchar mit 32 Bit steht?

    Sag ich dann einfach am Anfang von "Funktion_wchar.c":

    #include "header_by_me.h"
    
    #define SONDERDATENTYP
    
    void funktion(void){
       char name;
       ...
    }
    

    Habe ich damit mein Ziel erreicht, dass in "Funktionen_wchar.c" char immer für wchar steht?



  • Bzw. wo ist eigentlich der Unterschied zwischen

    #define wchar char

    und

    define wchar char

    ?



  • Wenn das irgendeinen Sinn haben soll, müsste das #include schon hinter das #define SONDERDATENTYP, sonst ist SONDERDATENTYP ja nicht definiert, wenn dein Header inkludiert ist...

    P.S.: Schonmal was von TCHAR gehört?

    P.P.S.: Was ist ein 16-Bit-char?



  • blubbII schrieb:

    Bzw. wo ist eigentlich der Unterschied zwischen

    #define wchar char

    und

    define wchar char

    ?

    Letzteres ist ein Syntaxfehler, der natürlich dann nicht auftritt, wenn wie hier:

    #ifdef SONDERDATENTYP
    define wchar char
    #endif
    

    SONDERDATENTYP nicht definiert wurde.

    MfG,

    Probe-Nutzer



  • Schönes Beispiel, Probe-Nutzer, wirklich. Aber ich glaube, das verwirrt ihn eher, als dass es hilft.. 😃

    Also: "define" gibt es in dieser Form natürlich nicht! Vielleicht hast du an "defined()" gedacht, denn das gib es wirklich?



  • Hallo,

    _matze schrieb:

    Schönes Beispiel, Probe-Nutzer, wirklich. Aber ich glaube, das verwirrt ihn eher, als dass es hilft.. 😃

    Ich habe doch nur auf diese eine spezielle Frage geantwortet, da gibt es nichts verwirrendes in der Antwort. Und das er

    #if defined
    

    im Sinn hatte, glaube ich wirklich nicht. Oder meintest du, ich hätte schreiben sollen, Präprozessoranweisungen beginnen immer mit einem #? Er hat sich eben nur gewundert, warum scheinbar auch das:

    #ifdef SONDERDATENTYP
    define wchar char
    #endif
    

    akzeptiert wird, und ich habe erklärt, warum.

    _matze schrieb:

    Also: "define" gibt es in dieser Form natürlich nicht! Vielleicht hast du an "defined()" gedacht, denn das gib es wirklich?

    Ja, aber dann bitte schön immer mit vorangestelltem #-Zeichen (nicht verwirrend, oder) 🙂

    MfG,

    Probe-Nutzer


Log in to reply