Habe ein Atmega32 Projekt, wo ich bis jetzt folgende Files habe:
ein Include-File wo ein Teil meiner Variablen deklariert sind.
ein Main-C File, wo meine Haupt-Anwendung steckt, mit ca. 500 Zeilen Code.
ein C-File, wo meine Service-Routinen stecken, mit ca. 400 Zeilen Code.
In beiden C-Files ist die Include-Datei, und weitere eingebunden.
In der Main-C steckt eine Timer/ISR Routine, die ich für das Display und andere Sachen, wie Sekunden-Timer, ect. benötige.
Diverse Variablen, wie z.B. Chip_Timeout sind mit 'volatile' erstellt. Erst in der Main, dann verschoben in der Header mit dem Zusatz 'EXTERN' . Also sollte ich doch von ALLEN C-Files darauf zugreifen können.
EXTERN volatile int Chip_Timeout;
Soweit funktioniert auch die Anwendung, inclusive Hardware.
Nun zum Problem:
Chip_Timeout funktioniert auch in der Main.c, da hier die ISR ist.
Ich benötige aber diesen Chip_Timeout aber auch in dem C-File, wo mein 'Service' - Zeugs ist. Und da klappt es nicht. Es kommt kein Fehler beim Build. Anscheinend wird die Variable (Chip_Timeout) in der ISR ignoriert, oder was ???
Wie kann man diese Problem lösen, damit Chip_Timout in beiden C-Files funktioniert ?
Wie kann man diese Problem lösen, damit Chip_Timout in beiden C-Files
funktioniert ?
Mit einem nachvollziehbaren Codebeispiel.
Sorry, die Prosa allein genügt bei sowas nicht. Falls du beispielsweise EXTERN wirklich so geschrieben hast - das gibt es in C nicht als Schlüsselwort …
Was ohne Grundlagenwissen einfach nur Schwachfug ist.
Nochmal, nimm dir ein C Buch zu Brust, oder besser sofort C++.
Aus Foren lernt man so nichts, oder oft auch das falsche.
Wie wie hier mal wieder gesehen haben.
Und das nicht zum ersten mal.
Nö, schon lange keins mehr gelesen. Von dem her kann ich gerade keins persönlich empfehlen.
Aber man bekommt definitv Skripte von FHs/Unis zum Thema. Und Bücher gab es auch schon immer kostenlose.
Aber der Compiler meckert nicht, und es funktioniert.
Offenbar ja nicht, sonst hättest du den Thread nicht begonnen.
Daher bat ich eingangs um ein nachvollziehbares Beispiel. Dieses sollte auf das Minimum zusammen gestrichen sein, mit dem man sieht, wie du das aufgebaut hast. (Ganz am Rande: wenn man sich die Arbeit macht, so ein Beispiel aus dem zusammen zu streichen, was man hat, versteht man häufig auch gleich sein Problem.)
wenn man sich die Arbeit macht, so ein
Beispiel aus dem zusammen zu streichen, was man hat, versteht man häufig
auch gleich sein Problem
Sein Problem ist, dass er den Unterschied zwischen Deklaration und Definition nicht kennt und deshalb nicht berücksichtigt.
Für mich war das seinerzeit beim Lernen anhand von K & R zunächst verwirrend, weil beide Begriffe in der Normalsprache ja ungefähr dasselbe meinen.
Wenn ich definiere, was ein "Hund" ist, dann entsteht dadurch kein konkreter Hund. Ich sage damit lediglich, wie ein Hund aussähe, wenn einer da wäre.
Nicht anders ist es, wenn ich vereinbare (deklariere), dass ich und andere ein Wesen mit bestimmten Eigenschaften (wenn denn ein solches Wesen da wäre) "Hund" nennen wollen. Wo ist da ein Unterschied?
In C entsteht durch eine Definition aber etwas durchaus Greifbares, nämlich ein reservierter Speicherplatz der definierten Größe im fertigen Programm; bei einer Deklaration entsteht gar nichts.
Sein Problem ist, dass er den Unterschied zwischen Deklaration und
Definition nicht kennt und deshalb nicht berücksichtigt.
Zumal eine Definition ja in der Regel auch zugleich eine Deklaration ist. ;-)
Sollte an sich trotzdem nicht zu dem beschriebenen Effekt führen: wenn sowohl Deklaration als auch Definition das "volatile" haben, dann müsste es funktionieren – und den Unterschied zwischen beiden hat er am Ende mit seinem Headerfile-Trick mit EXTERN unbewusst tatsächlich realisiert.
Ist doch aber noch mehr 'ne Krücke, als sauber verstanden zu haben, wo man eine extern-Deklaration und wo man die Definition hinpackt.
Prinzipiell gab es bei C auch noch die Möglichkeit, dass sich mehrere gleichnamige Definitionen einander überlagern (im Stile eines FORTRAN COMMON-Blocks), und das war lange Zeit sogar der Default. Ich bin mir nicht ganz sicher, aber ich glaube mich zu erinnern, dass das in C23 dann rausgeflogen oder zumindest deprecated ist.
Aber irgendwann ist doch auch mal gut mit den alten Zöpfen.
Warum? Was ist daran jetzt "besser"? Ist es nur besser, weil es neuer ist? Dann solltest Du Dich dafür einsetzen, daß Arduino nach Rust umzieht. Weil das ja neuer, ergo besser ist.
Für mich macht es das "besser"!
Du magst anderer Ansicht sein.
Ich würde sagen: "Einfacher" und "Selbstkorrigierend". Wenn man vergisst, die Variable anzulegen, dann passiert das einfach automatisch "irgendwo" im Hintergrund. Allerdings auch bei Schreibfehlern. Oder wenn der Linker eigentlich ein Problem melden sollte.
Für mich ist das ähnlich dem Wunsch, dass "der Compiler doch die schließende Klammer hinzudenken kann, wenn klar ist, dass sie fehlt".
Wenn man
vergisst, die Variable anzulegen, dann passiert das einfach automatisch
"irgendwo" im Hintergrund. Allerdings auch bei Schreibfehlern. Oder wenn
der Linker eigentlich ein Problem melden sollte.
Du hast eine witzige Fantasie, aber so funktioniert das nicht!
Dadurch, dass die inline Variable in der *.h definiert wird, gibt es diese in jeder Übersetzungseinheit, welche diese *.h einbindet.
Durch das inline Attribut wird dem Linker mitgeteilt, dass er sie alle zusammen legen soll, auf ein einziges Speicherobjekt.
Das gilt übrigens ganz ähnlich auch für inline Funktionen.
Methoden sind übrigens per default inline, wenn sie im Klassenkörper definiert werden. Und das ist schon viel länger so.
Das Prinzip wurde nur auf freie Funktionen und Variablen ausgedehnt, so dass es für den Programmierer gezielt nutzbar wird.
Da ist nix mit "automatisch" Klammern basteln, Schreibfehler korrigieren oder so....
Nix davon ist "Selbstkorrigierend".
Sondern das ist Teil der Sprachdefinition ab C++17
Das muss dir ja nicht schmecken, aber es ist jetzt so.
Auch kannst du weiterhin dein extern nach belieben weiter nutzen.
Nur so kann der Compiler prüfen, ob Deklaration und Definition vom selben Typ sind. Das ist extrem wichtig. Sonst könnte man in foobar.c die Variable auch abweichend als float definieren und keiner würde das merken!
Fazit:
In der Datei, wo die globale Variable definiert wird, sollte auch die externe Deklaration (in Form des include-Files) immer mit herangezogen werden, damit der Compiler prüfen kann, ob beide "kompatibel" sind.
Du hast eine witzige Fantasie, aber so funktioniert das nicht!
In C schon.
Das Prinzip wurde nur auf freie Funktionen und Variablen ausgedehnt, so
dass es für den Programmierer gezielt nutzbar wird.
Die ursprüngliche Bedeutung von inline war, den Aufruf möglichst schnell zu machen.
Dass es zur Definition im Header verwendet wird, ist eher eine Bedeutungsverschiebung. In C++ auch einleuchtend, da der C++-Compiler sich eh schon immer die Freiheit zum inline herausgenommen hat.