Das Video kommt von YouTube: erst beim Abspielen verbindet sich die Seite mit YouTube (Google).
04D.1 Funktion und Variable in eigene Datei auslagern; Header-Datei
Das Wichtigste aus dem Video
Tipp auf eine Zeit – das Video springt genau dorthin.
Transkriptautomatisch erstellt · 167 Zeilen
- so jetzt haben wir eben diese Funktion Würfel geschrieben schön ist wenn man Funktionen sauber zusammenfasst in einzelne Dateien nicht alle Funktionen
- in die Main Datei reinschmeißt die hier dass da nicht alle mögliche Krempel drin rumfliegt diese Funktion die soll in ihrer eigene Datei sozusagen sie bauen
- eine eigene Datei sowieso Punkt C und dazu Headerdatei um diese Funktion auszugliedern ich zeig noch mal wie man das im Prinzip machen würde fangen würde
- neue Datei hier File new file oder einfach hier mit dem leeren Blattpapier eine neue Datei die
- speichern save S in das Verzeichnis am besten wo auch sowieso die anderen Dateien vom Projekt drin stehen neben MC speichern ich nenne
- die jetzt mal ganz überraschend Würfel diese Datei die Datei soll nacher auch kompiliert werden also mausglick rechts
- hier add steht netterweise schon Würfel C das sind die Dateien die nachher kompiliert werden das sollte ich jetzt
- schon mal sagen kompiliert werden werden die c-dateien kompiliert werden nicht direkt die Header datateien die Headerdateien werden dann ja nachher mit
- include eingebunden so erfährt der Compiler von den Headerdateien hier das sind die c-dateien erstmal was der Compiler wissen muss über die c-dateien
- erfährt er von den Headerdateien wir brauchen eine cdatei da steht drinnen wie die wfunktion funktioniert von innen und wir brauchen eine Headerdatei mit
- den Deklarationen ich speicher das also als würfelpunkt H und sie schreiben jetzt mal was sinnvolles in diese cdatei und diese Header Datei
- includeegs und solche Geschichten in die cdatei in die cdatei kommt diese Kiste rein glaube jetzt muss
- ich tatsächlich mal die Aufgabe rauslöschen so das kommt in die cdatei wie sieht meine Funktion von innen aus die
- cdateien sind Zusagen sozusagen die echten Programme die werden ja auch kompiliert die stehen hier in der Liste für den
- Compiler damit haben wir erstmal die cdatei in der Header datatei steht wie diese Funktion von außen aussieht was muss der
- Wissen um diese Funktion benutzen zu können eine Deklaration das ist die Deklaration keine schweifklammern mit dem programmtex sozusagen dahinter mit
- dem Text der Funktion dahinter sondern ein Semikolon hinten dran zu sagen okay das ist der Name meiner Funktion sie nimmt nichts und gibt eine ganze Zahl
- das braucht man nachher um die andere Datei zu kompilieren diese Datei hier die Headerdatei wird inkludiert
- in meiner mainatei wie hier das include Matth genauso kann ich jetzt sagen include jetzt Anführungszeichen weil das mein eigenes meinem eigenen Verzeichnis
- steht Würfel h die headdatei wird inkludiert jetzt kann ich mir den hier ne wo ist er denn den wür schon rausgenommen schon
- und jetzt MS so funktionieren in Würfel h findet deriler die ktion von außen aussieht der Compiler fängt an die
- mainatei zu übersetzen mainatei die übersetzt der findet den würfelh wie die würbelfunktion von außen aussieht die Deklaration und kann sie hier
- verwenden der Linker bindet dann nachher alles zusammen was der Compiler kompiliert hat der Linke muss dann irgendwo aber auch wissen wie d die
- würfelfunktion wirklich geht und dann stellt er fest in dieser Datei die der Compiler auch übersetzt hat in dieser Datei findet er die würfelf tion und
- bindet die beiden zusammen jetzt müsste das theoretisch funktionieren jetzt soll ich das den kompilationsprozess gleich noch mal aufmalen aber kann mal gucken
- ob es wirklich tut soweit so gut ich gehe mal bis hinten durch das Ergebnis kommt mir fürchterlich bekannt vor wie
- eben das sind jetzt noch keine include Guards drin sicherheitalber oder hier Singular der include GU fehlt
- mir hier in dieser Datei noch muss ich gleich noch machen aber sicher aber noch mal zum kompilationsprozess was macht jetzt dieses System im
- Hintergrund wir haben eine Datei die heißt main.c wir haben eine Datei die heißt
- wfelc und wir haben eine Datei die heißt Würfel H der Compiler nimmt die main. C
- Datei und macht daraus Objektcode ich schreib nur o wie es auch immer gerade auf dem System heißt
- dasselbe mit der würfelcdatei der Compiler nimmt die würfelcdatei und macht daraus objektcod diese Datei wird als solche übersetzt halbw in
- Maschinensprache noch nicht ganz in Maschinensprache in der mainatei kommt jetzt aber unsere Funktion Würfel
- vor damit der Compiler diese Funktion kompilieren kann muss er wissen was sie denn tut nimmt die delzahlen hat die fünf Argumente hat sie sieben Argumente
- gibt sie bullch zahlen er muss nicht wissen wie diese Funktion wirklich funktioniert von innen aber muss wissen wie diese Funktion verwendet wird dazu
- brauchen wir die Header datatei das habe ich jetzt strategisch gut gemalt also hier die Header datatei die brauchen wir da die wird per include reingeholt die
- Headerdatei damit der Compiler die Deklarationen hat damit er weiß wie denn die würfelfunktion im Prinzip läuft damit das übersetzen kann hier in
- dem Objektcode steht ein Platzhalter weiterhin drin für die würfelfunktion die ich da jetzt gerade hingeschmiert habe im Objektcode steht weiterin
- Platzhalter aber der Compiler kann es kompilieren weil er weiß wie die würfelfunktion im Prinzip läuft das sind Header
- Datei der nächste compilerlauf ist die Würfel C Datei das sollte ich vielleicht auch noch mal an der Embedded Workbench zeigen Main C wird kompiliert und Würfel
- C wird kompiliert die c-dateien werden kompiliert die würfelcdatei wird kompiliert daraus wird Objektcode der Compiler läuft zweimal und dann kommt
- der Linker der kommt einmal und hier läuft jetzt zweimal für jede cdatei läuft der Compiler einmal und danach kommt der
- Linker der bindet das zusammen zu einer ausführbaren Datei unter Windows wäre das Exi hier ist es keine Exi sonder was fürchterliches egalter Windows wäre das
- ein Exel Datei so eine ausfühbare Datei das macht der Linker der Linker sieht hier den
- Querverweis oh ich brauch die würelfunktion und in der anderen übersetzten Datei sieht er die würfelfunktion und schafft die
- Verbindung linker verbinden to link das Zusammenbringen diese Arbeitsteilung ist eine Maßnahme um Zeit beim Kompilieren zu sparen stellen sich vor Sie haben
- wirklich ein Betriebssystem oder was mit 10tausenden an Dateien dann wollen sie nicht jedes Mal alle 10.000 Dateien übersetzen sondern nur die eine die sich
- geändert hat 999 bleiben so wie sie waren und zum Schluss bindet man dieses neue Ergebnis dann mit den anderen Sachen wieder
- zusammen das wird auf dies Weise schneller effizienter durch diese arbeitszahung mit dem Compiler und dem
- Linker und hier das ist jetzt eben der Ärger der Compiler hier an dieser Stelle muss wissen wie die würfelfunktion denn zu verwenden ist dafür die Header
- Datei dafür bin ich hier dafür dieses hier eine Deklaration jetzt weiß der Compiler wie es geht na ja wie die Funktion verwendet er
- weiß nicht wie die Funktion gemacht ist aber das ist ja auch egal das haben wir hier stehen die wird getrennt kompiliert der Compiler weiß wie die Funktion
- verwendet dafür hier Würfel h ich könnte überhaupt mal das auskommentieren das Würfel h was dann passiert project
- make dann sagt er uns dann sagt er uns function Würfel deced implicitly der C standandard erlaubt das
- noch ich verwende eine Funktion Würfel die der Compiler nicht kennt im c-standard ist tatsächlich dann vorgesehen dass der Compiler sich
- einfach selbst was erfindet dann wie diese Funktion zu verwenden wird zu verwenden sei die klärt implicitly das natürlich total heikel
- und das ist im allgemeinen ja auch Unsinn was ich der Compiler dann da selber ausdenkt in anderen Sprachen ist es schtiicht greifend verboten da darf
- nicht gerade irgendwas erfunden werden das passiert wenn der Compiler nicht weiß was da angesagt ist dafür den
- hier jetzt könnte ich noch ein typischen Fehler zeigen ich ma den H gerade mal wieder gut
- so wenn Sie hier die falsche Funktion bauen wen Sie hier die Funktion Würfel XY Z bauen ihr Hauptprogramm verwendet die Funktion Würfel ihre Headerdatei
- sagt auch was vom Würfel aber wird gar keine Funktion Würfel geliefert sondern Funktion Würfel XY
- Z jetzt gibt's wirklich ein Fehler undefined external Würfel hier behaupte ich es gäbe eine Funktion Würfel das ist ja hin der
- mainateil in der mainateil wird Würfel h inkludiert an dieser Stelle behaupte ich es gäbe eine Funktion Würfel irgendwo verwende sie
- auch und der Linker sie sehen hier error while running linker der Linker stellt dann fest beim zusammenbinden da hat mich jemand betuppt es gibt keine
- Funktion namens Würfel es gibt vielleicht eine XY Z aber das weiß der Linker nicht dass es die eigentlich sein sollte der der Linker sieht keine
- Funktion namens Würfel macht deshalb hier Ärger genau was hier steht für Würfel die Implementierung wie die Funktion
- funktioniert die habe ich natürlich jetzt aus Main C rausgeschmissen das wäre auch noch eine spannende Geschichte was passiert wenn ich hier in der
- mainatei die auch noch mal drinen habe project make aha entry Würfel in Module Main blablabla
- redefined in Module Würfel eine erneute Definition und das hat natürlich wieder der Linker gemerkt der Linker sieht in der einen Datei mach das noch mal auf
- hier meine seh händische Skizze der Linker sieht in dieser Datei gibt's eine Funktion namens Würfel implementiert in dieser Datei gibt Funktion namens Würfel
- implementiert und dann sagt der Linker so nicht ich kann nicht zwei Sachen mit demselben Namen haben an der Stelle zumindest nicht sonst viicht schon aber
- an der Stelle nicht das ist dieser Fehler hier das ist wirklich ein Fehler so also hier aus der mainatei nehme ich die Funktion noch mal raus mit
- den Namen das muss ich vielle gerade noch mal sagen ich habe jetzt diese cdatei Würfel genannt und die H Datei Würfel genannt weil es für mich
- vielleicht da verständlich ist dass die Funktion Würfel heißt heißt nicht dass die Dateien auch Würfel heißen müssen vielleicht sollte ich noch mal hier klar
- machen ich schreib hier Würfel werfen was müsste ich jetzt alles umbenennen genau an zwei weiteren Stellen Datei heißt jetzt weiter
- würfelpt C hier in der Header Datei brauche ich dann den anderen Namen ich deklariere jetzt ja eine andere Funktion die Würfel werfen heißt und in der
- mainatei der Name der Datei ist derselbe aber da wo ich da wo ich die Funktion habe ich alle jetzt da noch einer da wo ich die Funktion anwende da brauche ich
- jetzt den anderen Namen mal gerade gucken project make wo ich dabei bin sie sehen noch mal die drei Arten wie Funktionen in C
- vorkommen das erste ist dass so eine Funktion eine Implementierung haben muss eine Definition sagt man dann C so wird die Funktion gemacht das Rezept
- ausbuchstabiert die Definition dann gibt es eine Deklaration die steht typischerweise in
- der Headerdatei die Deklaration wie sieht die Funktion von außen aus nicht wie sie von innen funktioniert keine Implementierung sondern nur wie sie
- verwendet wird was geht rein was geht raus vom Typ her Deklaration und dann gibt's den Aufruf einer Funktion das hier ist der Aufruf einer Funktion sie
- wird wirklich ausgeführt jemand kocht die Suppe nach dem Rezept
- noch mal was zu Deklarationen das kam ja dieses Semester noch nicht so ganz ausführlich dran in den Videos kam es irgendwo dran aber das war vielleicht
- ein bisschen zu unterschwellig in der Headerdatei da steht so eine Deklaration der C Compiler will bevor er eine Funktion und
- andere Sachen verwendet mindestens eine Deklaration sehen ich zeige mal sowas int F von mir aus eine Funktion heißt F und sie kriegt eine ganzsalige
- Variable und gibt von mir aus 23 zweimal zweimal diese ganzzealige Variable zurück jetzt eine andere
- Funktion die die erste verwendet hier könnte z.B sowas stehen wie return 3 mal F von X eine Funktion g die Funktion f verwendet wenn die in dieser Reihenfolge
- stehen dann ist der cciler glücklich es se die Funktion f hätte schon gegeben Entschuldigung die gibt's
- hier unten schon dann heißt jetzt eben F1 da unten sorry kleiner Showstopper noch mal project make so also ich kann eine Funktion verwenden wenn sie vorher
- definiert ist wenn die Implementierung vorher steht dann ist der ccpiler glücklich dann weiß er wie die geht sie können aber auch die Reihenfolge
- ändern dass sie die Funktion erst verwenden und dann im Compiler mitteilen wie die Funktion denn zu machen ist aber dann zeig jetzt einmal so was jetzt
- passiert jetzt gibt nämlich erstmger pro make jetzt haben wir wieder Dec implicit die Funktion f hat er hier oben nicht gehabt und hat sich was erfunden nicht
- gut aber wir können den Ärger verhindern mit einer Deklaration so sie deklarieren die Funktion f wie versprechen es gibt hier irgendwo
- eine Funktion f die nimmt eine ganze Zahl und liefert eine ganze Zahl jetzt ist der Compiler glücklich wenn er die Funktion g bauen will soll hier kan er
- den kann er die Funktion f dann einsetzen und hier unten erfährt er wie die Funktion f wirklich funktioniert ich ma mal
- make so geht das also wenn Sie eine Deklaration haben dann kann der Compiler auch die Funktion verwenden und das haben im Endeffekt mit der Header Datei
- in der Headerdatei steht die Deklaration drin und deshalb kann der Compiler die Funktion verwenden das ist hier eine sag mal ihr weniger typische Art Deklaration
- zu verwenden dass wir eine Funktion erst deklarieren und später definieren in derselben Datei normalerweise wird man die Deklaration in die head datatei
- schreiben und die Definition in die cdatei schreiben ich sollte noch der formher vielleicht vorschreiben das ist die
- Deklaration das hier unten ist die Definition und dieses hier ist der Aufruf einer
- Funktion drei Arten wie Funktionen vorkommen soll ich etwas klarer machen F von X das ist der Aufruf nicht dreal F von X F von X ist der Aufruf der
- Funktion ihr könnte auch übrigens damit da keine Bedenken gibt 4 + X drin F V 4 + X wäre dann der
- Aufruf jetzt noch der include Guard diese Headerdatei die sieht so aus wie man sie normalerweise nicht schreiben würde hier wä es kein Problem später ist
- es ein Problem des machen wir das sofort richtig ich zeige das noch mal hier in der Skizze es könnte sein dass ein eine cdatei was heißt es könnte sein später
- im Leben ist es dann so dass in einer cdatei ganz viel Headerdateien inkludiert
- sind und dann gibt's den Ärger es ist auch möglich in Headerdateien Header datateien zu inkludieren und auch sinnvoll denken Sie
- an messpt H brauchen sie irgendwo den Sinus oder Standard buol sie brauchen irgendwo in der Header datatei fals und true dann brauchen Sie Standard buol
- stell sowas vor wie Standard buol Standard BU könnte als solches wieder in Headerdateien inkludiert sein dann hab wir zum Schluss den Ärger es kann
- passieren dass beim Kompilieren dieselbe h datatei mehrfach vorkommt weil sie in der einen h datatei vorkommt und in der anderen head Datei vorkommt noch mal mit
- includes das hört sich esoterisch an aber wenn sie wirklich ein vernünftig großes System haben D mit 20 30 Dateien wird es regelmäßig passieren dass sie
- includes in includes haben und head Dateien im Endeffekt mehrfach vorkommen damit das keinen Ärger gibt zweimal Datei in den Compiler nicht so
- gut damit das keinen Ärger gibt dafür gibt's den include Guard und zwar so jetzt kommt der Präprozessor und das
- ist eigentlich das einzige was man heute noch mit Präprozessor machen sollte es seit den man hat Antike Software also eine Anweisung an den prprozessor if Def
- wenn nicht definiert und zwar ein Symbol dies Symbol wird man sich typischerweise aus dem Dateinamen damit es eeutig ist Würfel unr h wird man das gerne nennen
- wenn dieses Symbol nicht definiert ist dann nehme alles was dahinter steht was ich jetzt mache ist okay wenn das nicht definiert ist dann sage ich
- dann definiere ich das Symbol define [Musik] def ist sozusagen schweifklommer
- zuif das ist der include Guard das sieht wenn man zum ersten Mal so sieht sieht es haarsträubend aus wenn sie sich solche Dateien wie mess.h oder
- standardlip. angucken stellen Sie fest oh das kann man auch noch weiter treiben aber das ist Derg in Standardform in Reinform wenn der prprozessor also das
- was vor dem Compiler läuft wenn der prprozessor diese Datei zum ersten Mal sieht weiß er nichts von einem Symbol namens würfel_terrich h na schön denkt
- er sich mach wir weiter if not defined es ist nicht definiert also macht er weiter es ist nicht definiert dann definiert er das Symbol als nicht sie
- könnten hier auch irgendwas hinterschreiben dann wird er das Symbol als GK was auch immer definieren er definiert das Symbol als nichts aber das
- Symbol ist jetzt definiert er liest die Deklaration sozusagen schweifklammer zu Ende wenn jetzt bei demelben
- kompilationslauf für dieselbe c-datei diese Datei noch mal vorkommt sieht der Präprozessor oh ich habe schon ein symbolnamens Würfel h es ist definiert
- und er überspringt bis dahin und und damit ist der Teil hier in der Mitte hier nur einmal gelesen wollen beim zweiten Mal gibt es dieses
- Symbol und das ganze was in dem iF drin wird übersprungen das ist der Trick bei den include GUID das ist eine historische Kiste die irgendwie nicht
- wegzukriegen ist einige Compiler Hersteller haben etwas das nennt sich pragma W stattdessen aber das ist
- offiziell nicht standardisiert das wird auf jeden Fall funktionieren letzte Geschichte mit dem zufallsding damit sie einmal noch mal
- die cdatei und die Header datatei anfassen geh noch mal in die cdatei hier gibt's ja meine interne Zahl a die jedes
- mal irgendwie weitergestellt wird und ich möchte gerne dass man diese Zahl aber auch einstellen kann dass man
- insbesondere zu Beginn des Programms z.B a mit Hilfe der Uhrzeit oder irgendeiner Messung oder was auch immer einstellen kann dass es sich zufälliger anfühlt
- schreiben Sie eine Funktion mit deren H für Sie diese Zahl a einstellen können wird natürlich noch so ein paar andere Änderungen nach sich
- ziehen diese Funktion die fängt ja immer an in dem A = 42 ist zu Beginn des Programms ich kriege immer dieselbe FG an Zufallszahlen ab Programmstart ich
- möchte gerne zu Programmstart oder auch zu anderen Zeitpunkten eine andere Zahl einstellen können für a damit ich nicht immer wieder dieselbe Folge Kriege oder
- sogar auch um dieselbe Folge tatsächlichoduzi zu könen wenn zum Schluss wieder auf 42 stellen dann fängt da ja wieder
- an diese Variable a die darf jetzt nicht mehr einfach innerhalb dieser schweifklammern stehen diese Variable a muss auch in einer anderen Funktion
- zugänglich sein wir nehmen die da raus das war mein Gedanke den habe ich etwas kriptisch formuliert so haben sie eine statische variable innerhalb der
- Datei diese Variable ist jetzt in der Datei Würfel C sichtbar und sonst nicht eine statische variable wenn Sie das hier weglassen können Sie die Variable
- auch sogar aus anderen Dateien sehen wollen sie aber typischerweise nicht lieber verbergen eine statische variable innerhalb der
- Datei und jetzt brauche ich noch eine Funktion mit der ich diese Variable setzen kann eine Funktion die also nichts
- zurückliefert seed würde man die ja normalerweise nennen sehen
- heißt auch in C s Rand se random dieser Funktion gebe ich ebenso ein Bit ohne
- Vorzeichen B Beit ist und schmeiße dieses B in a rein das war was mir vorgeschwebt hat größer
- hier so in der Datei C gibt es jetzt also versteckt in der Datei sollte ich sagen gibt es eine Variable namens a zwei Funktionen greifen auf diese
- Variable zu seed und Würfel werfen zu programmbegn wird die Variable auf 42 gesetzt mit seed können Sie diese
- Variable auf ein anderen Wert setzen den sie wollen und mit Würfel werfen na ja passiert dasselbe was vorher passiert ist dieses a greift in
- beiden Fällen auf diese Variable zu und dieses a hier ist nicht haben wir hier auch noch ein a genau das ist ein anderes a dieses a hier ist eine lokale
- Variable in der Funktion Main das ist für den Compiler als ob der hier Karl Egon heißen würde und als ob dieses hier ernst augus heißen würde dieses a die
- heißen für uns als Menschen gleich die beiden Variablen aber für den Compiler sind das zwei paar Schuhe das ist immer ein bisschen schwierig am
- Anfang ich zeige gerade noch mal was hier wirklich passiert statics so geh auf in der Datei Würfel gibt es
- die statische variable static namens a und die steht schon auf irgendeinem Wert 2 x 16 + 10 42 Überraschung also diese Variable a steht schon auf irgendeinem
- Wert in dieser Datei Würfel C ist die versteckt jetzt fange ich hier an zu arbeiten in meiner
- mainfunktion guck mal bei Locals da gibt's auch eine Variable a das ist diese hier die heißt zufällig so diese lokale Variable wie diese statische
- Variable in der anderen Datei aber das stört den Compiler nicht das sind zwei verschiedene Sachen ich zeig so ausführlich weil das oft missverstanden
- wird wenn zwei Variablen gleich heißen heißt das nicht das ist die gleichen Sinn es hängt von den Umständen ab wie die verwendet werden wo sie definiert
- werden korrekter Einwand ich müsste die Funktion natürlich auch
- verwenden seed wird ja noch gar nicht verwendet haben sie aufgepasst was müsste ich jetzt überhaupt tun damit ich diese Funktion seed verwenden
- kann also die müsste deklariert werden Würfel werfen hatten wir deklariert in der Headerdatei seed müssten wir auch deklarieren also den hier einmal
- kopieren c h so jetzt habe ich dann auch eine Deklaration diese Deklaration in der
- Header Datei wird in der mainatei eingelesen an dieser Stelle erfährt unsere mainatei erfährt der Compiler beim Verarbeiten
- der mainei so an dieser an dieser Stelle erfährt der Compiler beim Verarbeiten der mainei dass es so eine Funktion seed
- gibt die einen bit ohne Vorzeichen nimmt und nichts lief an der Stelle und deshalb kann ich sie jetzt verwenden hier z.B sagen
- seed 42 wird natürlich genau das machen was wir vorher hatten also 43 hier müsste jetzt irgendwas stehen wie hole die aktuelle Uhrzeit nicht die
- Zahl 43 sondern die hle hole die aktuelle Uhrzeit oder wenn Sie sagen wollen ich hätte gerne noch mal die selbe Folge an
- Zufallszahlen auf diese Weise geht's dann hier wieder los mit derselben Vorg Zufallszahlen weil sie denselben Wert a noch mal haben so würde das Ding dann
- verwendet werden jetzt müssten wir sogar andere Ergebnisse haben für die Statistik mal gucken was der dazu
- sagt Locals oh ja Mittelwert ist jetzt 3,45 sind auch tatsächlich andere Zahlen die rauskommen