Hallo ihr Experten, ich bekomme beim kompilieren immer eine "implicit declaration" Warnung. Das Programm läuft zwar trotzdem korrekt aber ich wüsste gerne warum das falsch ist. Konkret geht es um den Aufruf einer Funktion innerhalb einer If Abfragefunktion. Dort wird aufgerufen: void tasterabfrage(void) { if (taster ==1) { timereset(); } } Die aufzurufende Funktion selbst ist folgendermaßen deklariert: void timereset(void) { variable1=variable2; }
:
Verschoben durch Admin
C Grundlagen. Schiebe mal die Funktion void timereset(void) vor die tasterabfrage. Alternativ kannst du am Anfang deiner C-Datei auch schreiben:
1 | void timereset(void); |
Warum, dazu lese dich mal in C Grundlagen ein.
Die Reihenfolge ist nicht ganz unwichtig. Die Deklaration muß vor dem ersten Aufruf stehen, ansonsten kennt der Compiler die dort noch nicht. Daher schreibt man die Deklaration an den Anfang.
1 | void timereset(void); |
Oliver
Hi, die Funktion ist aber erst definiert, nachdem Du sie schonmal genutzt hast. Deshalb gibt es bei der Benutzung eine Warnung und der Compiler macht wüste Spekulationen über Parameter und Rückgabewert sowie deren Datentypen. Also zunächst alle Funktionen deklarieren :
1 | void tasterabfrage(void); |
2 | void timereset(void); |
So etwas kann gerne auch in einer Header-Datei geschehen, wenn die Funktionen in mehreren Quelltexten genutzt werden. Dann die Funktionen nach und nach definieren :
1 | void tasterabfrage(void) |
2 | {
|
3 | ...
|
4 | }
|
5 | |
6 | void timereset(void) |
7 | {
|
8 | ...
|
9 | }
|
Wenn Du es ganz fein säuberlich machen willst, achtest Du darauf, dass es nur genau eine Deklaration für jede Funktion gibt (für Variablen gilt das ähnlich). Sprich, wird die Funktion in einer .c - Datei verwendet, steht die Deklaration vor den Funktionsdefinitionen in dieser .c - Datei. Und damit sich auch kein anderer Quelltext dran vergeht, sind die Funktionen als static gekennzeichnet. Brauchst Du die Funktion in mehreren Quelltexten, so schreibt man die Deklaration einmal in einer .h-Datei. Wobei auch die .c-Datei, die die Funktion definiert, jene .h-Datei einbindet. Das stellt sicher, dass sich alle einig sind, welchen Typ Rückgabewert und Parameter haben. Weil merke : wenn es mehrere Deklarationen gibt, könnten sie unterschiedlich sein. Und weil laut Murphy alles schief geht, was schief gehen kann, werden sie irgendwann unterschiedliche Parametertypen haben, was zu witzigen, aber schlecht zu behebenden Fehlfunktionen führt. Und bitte jetzt nicht damit kommen, dass das bei Arduino auch anders geht. Ja, die haben einen Parser eingebaut, der zu allen Funktionen Deklarationen erstellt und automatisch dem Compiler zur Verfügung stellt, so dass sich Programmieranfänger damit nicht herumplagen müssen.
Ralf schrieb: > ich bekomme beim kompilieren immer eine "implicit declaration" Warnung. > Das Programm läuft zwar trotzdem korrekt aber ich wüsste gerne warum das > falsch ist. Es gibt Programme, die ohne (korrekte) Prototypen nicht korrekt übersetzt werden (können). Um solche Fehler zu vermeiden, warnt gcc — und zwar auch dann, wenn der erzeugte Code das tut, was er soll. Daher wird für avr-gcc empfohlen, auch folgende Schalter bzw. Diagnostics zu aktivieren: -Wmissing-prototypes -Wstrict-prototypes Weil es wie gesagt für manche ABIs / Architekturen sein kann (z.B. für avr) dass ohne Prototypen kein funktionales Programm zu erhalten ist, sollten man jedoch die strikteren -Werror=missing-prototypes -Werror=strict-prototypes verwenden.
Wenn die Funktionen in einer Datei stehen und man keine Deklarationen macht/machen will, dann muss die Funktion, die zuerst in einer Routine benutzt wird, auch zu oberst im File kommen. Weil das umständlich ist, den Code darauf zu prüfen, macht man die genannten Deklarationen.
Hi Johann, danke für den Hinweis. Gibt es noch andere Empfehlungen, welche Warn-Parameter man aktivieren sollte, um ähnliche Probleme schnell aufzudecken? Ich mache immer -W -Wall -Wextra -Wstrict-overflow -Waddr-space-convert. Aber das scheint ja nicht der Weisheit letzter Schluss zu sein. Zumindest hat dein Hinweis bei einem meiner Quelltexte ein kleines Problem zu Tage gefördert.
Ein -Wall sollte das -W ersetzen. :-) Ansonsten ist vielleicht noch -pedantic hilfreich.
-pedantic spuckt halt viel wirres Zeug aus, das nicht wirklich weiter hilft. Alleine die ganzen Warnungen zu Binärkonstanten (die ich zu Hunderten benutze) überfluten den Bildschirm völlig.
Der Sinn von Warnungen ist es, dich auf Dinge hinzuweisen, die du anders besser machen könntest. Auch wenn ein pedantischer Compiler meist nur auf Prinzipien rumreitet, so ganz unrecht hat er meist nicht. :-) Es gibt in C keine Binärkonstanten, also ist dein Code schonmal kein C. Egal, wie offensichtlich es ist, was du hinschreibst. ;-)
Fakt ist, dass Binärkonstanten aber korrekt implementiert sind und funktionieren und sicher auch nicht geplant ist, dieses jemals wieder aus dem gcc zu entfernen. Diese Warnung ist völlig praxisfern und mutet steinzeitlich an. Genauso die Warnung vor doppelten Semikola. Wer Binärkonstanten benutzt, tut dies aus gutem Grund. Meinst du, der Code wird lesbarer und besser, wenn ich es als Hex oder Dez schreibe und beim Verstehen des Codes jedesmal im Kopf rechnen darf!? Ist aber auch egal. -pedantic führt keine anderen hilfreichen Meldungen zutage, so wie es z.B. -Wmissing-prototypes tat. Meine Frage war, ob es noch mehr praxistaugliche Warn-Schalter gibt, die man auch sinnvoll verwenden sollte.
Tim schrieb: > Meinst du, der > Code wird lesbarer und besser, wenn ich es als Hex oder Dez schreibe und > beim Verstehen des Codes jedesmal im Kopf rechnen darf!? Der Code wird besser, wenn du den Compiler rechnen lässt und Namen für Konstanten vergibst. Binärkonstanten sind überflüssig.
Tim schrieb: > Fakt ist, dass Binärkonstanten aber korrekt implementiert sind und > funktionieren und sicher auch nicht geplant ist, dieses jemals wieder > aus dem gcc zu entfernen. Auf allen Architekturen? Das war m.W. lange eine Spezialität vom AVR-GCC. Tim schrieb: > Genauso die Warnung vor doppelten Semikola. Sowas nehme ich - wie auch Leerzeichen am Ende der Zeile - als oberflächliches Maß für die Qualität eines Quelltextes. Im Sinne von: Wie ordentlich hat der Autor gearbeitet. Einen Text bewerte ich auch nach der Rechtschreibfehlerdichte. Wem die Form egal ist, dem kann auch der Inhalt nicht sehr wichtig sein. Tim schrieb: > Meinst du, der Code wird lesbarer und besser, > wenn ich es als Hex oder Dez schreibe und > beim Verstehen des Codes jedesmal im Kopf rechnen darf!? Wenn du sinnvolle Namen benutzt, ja. Auf einem 8-Bitter kann man Binärkonstanten noch sinnvoll einsetzen, auf einem 32-Bitter nicht. Tim schrieb: > Ist aber auch egal. -pedantic führt keine anderen hilfreichen Meldungen > zutage, so wie es z.B. -Wmissing-prototypes tat. "Hilfreich" ist aber deine persönliche Meinung. ;-)
:
Bearbeitet durch User
S. R. schrieb: > Der Sinn von Warnungen ist es, dich auf Dinge hinzuweisen, die du anders > besser machen könntest. Eigentlich ist der Sinn, auf Dinge hinzuweisen, die mit einer gewissen Wahrscheinlichkeit fehlerhaft sind. Die kann man dann nicht besser machen, sondern richtiger. Oliver
Tim schrieb: > Fakt ist, dass Binärkonstanten aber korrekt implementiert sind und > funktionieren und sicher auch nicht geplant ist, dieses jemals wieder > aus dem gcc zu entfernen. Diese Warnung ist völlig praxisfern und mutet > steinzeitlich an. Genauso die Warnung vor doppelten Semikola. Das hat nichts mit "steinzeitlich" zu tun. Das Handbuch sagt explizit folgendes zu -pedantic: "Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used." Es ist also genau dafür da, bei allem zu warnen, das nicht strikt ISO-C ist, oder anders gesagt, bei Konstrukten, für die ISO C vorschreibt, dass der Compiler mindestens warnen muss. > Ist aber auch egal. -pedantic führt keine anderen hilfreichen Meldungen > zutage, so wie es z.B. -Wmissing-prototypes tat. Wenn man nicht an ISO-C-Konformität interessiert ist, dann mag das sein.
Oliver S. schrieb: > Eigentlich ist der Sinn, auf Dinge hinzuweisen, die mit einer gewissen > Wahrscheinlichkeit fehlerhaft sind. Wenn du Dinge tust, die nicht dem C-Standard entsprechen, dann sind sie entsprechend des C-Standards ziemlich sicher fehlerhaft (d.h. implementation-defined oder undefined). Falls dich das nicht interessiert, programmierst du kein C, sondern einen C-ähnlichen Dialekt des gcc auf einer bestimmten Architektur. Wieviel "avr-gcc" für dich akzeptabel ist, kannst nur du wissen. Ich habe dir "-pedantic" auch nur vorgeschlagen, eben aus diesem Grund.
S. R. schrieb: > Wieviel "avr-gcc" für dich akzeptabel ist, kannst nur du wissen. Ich > habe dir "-pedantic" auch nur vorgeschlagen, eben aus diesem Grund. Ich bin vermutlich nicht das du, das du meinst, aber egal. Oliver
Tim schrieb: > Alleine die ganzen Warnungen zu Binärkonstanten (die ich zu > Hunderten benutze) überfluten den Bildschirm völlig. Macht der das auch wenn man Gnu Extensions über --std=gnu11 einschaltet? Kann aber sein, weil das IIRC nur auf AVR tut. Hunterte Binärkonstanten sind aber auch eher schlechter Stil, da die IMHO fehlerträchtiger als Hex sind.
Oliver S. schrieb: > Ich bin vermutlich nicht das du, das du meinst, aber egal. Stimmt, ich meinte Tim - also den, von dem die letzte Diskussion ausging. :-)
:
Bearbeitet durch User
Ja, auch dann. Die Binärkonstanten sind alles Sachen, wo man gleich erkennen sollte, welches Bit gesetzt ist oder nicht. Beispiel: Konfiguration von I2C-Geräten. Wenn ich da Hex oder Dez schreibe, kann ich das nicht sofort sehen. Aber ist auch egal. Pedantic ist nicht für mich geeignet, da es keinen Informationsvorteil bringt. Aber eventuell hat ja noch einer einen Geheimtipp für andere Warnschalter.
Tim schrieb: > wo man gleich erkennen sollte, welches Bit gesetzt ist oder nicht. Dafür sind Binärkonstanten aber auch nicht hilfreich. Besser sind sprechende Namen der Bits bzw. der Bit-Werte, die dann mit OR kombiniert werden. So macht es der Rest der Welt. Ansonsten ist der intellektuelle Sprung zu tatsächlich standardkonformen Hexadezimalkonstanten nun wirklich nicht gigantisch; man muss nur 16 Bitkombinationen "lernen", um ein Nibble zu verstehen. Damit beschäftigt man sich mal 'ne Woche lang, dann kann man's für den Rest des Lebens und braucht keine Binärkonstanten. Die werden obendrein bei mehr als 8 Bit reichlich unübersichtlich, was man von Hexkonstanten erst jenseits der 32 Bit sagen kann.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.