Hallo. Ich habe software für den AVR ATMega 16 mit dem ICC-AVR-Compiler geschrieben. Habe da ein paar Fehler, die ich hier noch nicht näher beschreiben will, um diese Frage nicht in irgend eine Richtung zu leiten. Beim compilieren des Projekts bekomme ich die Warnung: ... missing prototype und ... declaration of `Set_DMode' does not match previous declaration at X:\En.... Beim compilieren ohne ANSI C Prüfung wird noch gemeldet: ... calling function without prototype may cause errors Diese Meldungen treten auf, wenn folgender Fehler gemacht wird: Eine Funktion wird in der C-Datei geschrieben. Diese Funktion ruft eine andere Funktion in der gleichen C-Datei auf. Beide Funktionen sind in der H-Datei aufgeführt. Die H-Datei ist nur im Hauptprogramm eingebunden, aber nicht in der C-Datei, in der die Funktionen stehen. Somit weiß der Compiler wohl nicht, wo die Funktion, die intern aufgerufen wird, steht. Wie gesagt, der Fehler ist behoben, wenn die H-Datei in der C-Datei eingebunden wird. Nur was kann geschehen, wenn man die Warnungen ignoriert und die Software laufen läst? Weiß das jemand? Ich möchte wissen, ob die Fehler, die ich beobachtet habe, darauf zurück zu führen sind. Leider passieren diese Fehler nicht bei mir im Labor, sondern nur im Feld, sodass ich das nicht einfach prüfen kann. Gruß Rasmus
> Nur was kann geschehen, wenn man die Warnungen ignoriert und die > Software laufen läst? Alles mögliche kann passieren. Die Warnungen bedeuten in diesem Fall ja nur, dass der Compiler bestimmte Dinge nicht überprüfen kann. Er muss es nicht überprüfen, der C-Standard schreibt es nicht vor, daher sind es nur Warnungen und keine Fehler. Nun kann es natürlich sein, dass alles in Ordnung ist und der Programmierer aufgepasst hat. Dann passiert gar nichts, das Program läuft und läuft und läuft. Es kann aber auch sein, dass der Programmierer einen Fehler eingebaut hat, den der Compiler aufgrund eben dieser nicht durchführbaren Prüfungen nicht entdecken kann. In dem Fall sind Tür und Tor offen. Alles mögliche kann passieren: Das Pgm stürzt ab, deine Festplatte wird formatiert, das Ventil zur Blutzufuhr in der angeschlossenen Dialysemaschine schliest sich; der Patient stirbt deswegen, in dem zu steuerndem Kernkraftwerk geht der Reaktor hoch. Stell dir einfach den schlimmsten möglichen Fall vor und mal ihn dir noch schlimmer aus. Genau das wird irgendwann passieren. Natürlich nicht bei deinen Labortests, sondern erst wenn das Programm im Einsatz ist oder du es das erste mal dem Kunden vorführst. > Somit weiß der Compiler wohl > nicht, wo die Funktion, die intern aufgerufen wird, steht. Nein. Das ist dem Compiler sowieso egal. Das ist Sache des Linkers. Für den Compiler ist nur interessant: * Welche Argumente nimmt die Funktion. Stimmt beim Aufruf die Anzahl und der Datentyp aller Argumente überein * Welche Argumente muessen mit einem impliziten Cast an die von der Funktion erwarteten Datentypen angepasst werden und: geht das auch. * Welchen Rückgabetyp hat die Funktion. Diese Information entnimmt der Compiler dem Prototypen. Hat er keinen zur Verfügung, dann * gibt es eine Warnung * vertraut der Compiler darauf, dass der Programmierer die Argumente (inklusive ev. notwendiger Casts) schon richtig gemacht haben wird * Es gelten Standard Annahmen für Argumentdatentypen. Zb. wird ein char immer als int übergeben und ein float wird auf double hochgecastet. * gilt die Default-Annahme, dass die Funktion einen int zurückliefert. Zum Abschluss noch: Einem Programmierer, der eine derartige Warnung ignoriert, würde ich persönlich die Hammelbeine langziehen.
> ... declaration of `Set_DMode' does not match previous declaration at > X:\En.... Da haben wir doch schon was. Dem solltest du auf jeden Fall nachgehen. Das könnte die Ursache für Szenario 2 sein.
Hallo. Danke für die schnelle Antwort. Hat nichts mit Medizin oder KAWs zu tun also keine Sorge!!!! ;-) Aber die Meldung > ... declaration of `Set_DMode' does not match previous declaration at > X:\En.... ist weg, wenn die H-Datei eingebunden ist, also die Funktion scheint richtig vereinbart zu sein. Gruß Rasmus
Ehrlich gesagt sind exakt dies die Gründe warum ich C nicht sonderlich mag, im Vergleich zu anderen restriktiveren Programmiersprachen. Das soll jetzt kein Flamewar werden, Gott bewahre. Wenn der Compiler auf Grund von Fehlern des Programmieres keine exakte Entscheidung treffen kann dann erwarte ich das er seine Arbeit mit einer klaren Fehlermeldung abbricht und nicht irgendwie versucht das "nicht Machbare" denoch hinzubiegen. Mir ist sehr wohl klar warum der C Compiler so und nicht anders arbeiten muß (benötige also keine weiteren Erklärungen), wollte eben nur darauf hinweisen das es dieses Verhalten ist das meiner Meinung nach im Vergleich zu anderen Sprachen ein "Konstruktionsfehler" darstellt. Gruß Hagen
>> Aber die Meldung >> ... declaration of `Set_DMode' does not match previous declaration at >> X:\En.... > > ist weg, wenn die H-Datei eingebunden ist, also die Funktion scheint > richtig vereinbart zu sein. Das deutet darauf hin, dass du genau den Fall hattest: * Der Compiler hatte keinen Prototypen * also hat er, wie oben beschrieben, beim Aufruf Standardannahmen angenommen um den Aufruf compilieren zu können. Dabei hat sich der Compiler auch sowas ähnliches wie einen Prototypen für diese Funktion zurechtgelegt. * In weiterer Folge ist der Compiler dann auf Funktion gestossen und hat gemerkt, dass sein selbst generierter Prototyp nicht mit der tatsächlichen Implementierung übereinstimmt. D.h. die Standard-Annahmen, die beim Aufruf gemacht wurden waren falsch. Wie gesagt: Hammelbeine langziehen. Man nimmt vom Compiler jede Hilfe die man kriegen kann. Und man arbeitet solange am Code, bis alle Warnungen weg sind! Eine Warnung ist wie ein Fehler zu werten. Sie kann harmlos sein, muss aber nicht.
> Wenn der Compiler auf Grund von Fehlern des Programmieres > keine exakte Entscheidung treffen kann dann erwarte ich das > er seine Arbeit mit einer klaren Fehlermeldung abbricht Beim GCC einfach die Optionen "-Wall -Werror -pedantic-errors" setzen. Dann passiert genau das.
> wollte eben nur darauf > hinweisen das es dieses Verhalten ist das meiner Meinung nach im > Vergleich zu anderen Sprachen ein "Konstruktionsfehler" darstellt Ist schon OK. Ich (und viele andere) gehe da durchaus mit dir konform. Zur Ehrenrettung muss man halt sagen, dass einiges davon schon auch historisch bedingt ist. Auf der Ur-PDP wa rhalt nicht massig Platz und ich denke auch man wollte schnell einen Compiler haben. Und wie es halt dann so ist: irgendwann ist es zu spät und man kann ein grundlegendes Verhalten der Programmiersprache nicht mehr ändern. Soweit ich aber weiss (oder glaube mich zu erinnern) soll aber in diesem speziellen Punkt eine Angleichung von C an C++ erfolgen: * Die Implizit-Int Regel fällt weg * Prototypen werden obligatorisch
Der Grund für die "implizit-Int"-Regel liegt in "legacy-code", der noch im alten "K&R"-Stil geschrieben ist - ohne Prototypen, fast vollständig ohne Typüberprüfung ... Das wurde bei der Einführung von ANSI-C bewusst zugelassen, weil sonst alle bis dahin geschriebenen Programme sich nicht mehr hätten übersetzen lassen. Beispiel
1 | my_function(a, b) |
2 | int a; |
3 | int b; |
4 | {
|
5 | dosomething(a, b); |
6 | return 1; |
7 | }
|
das verhalten, das du beschreibst passiert wenn: ...du eine funktion schreibst, diese aber im c-file (vor der main-funktion) nicht bekannt gemacht wird. wenn du also zb schreibst: void myfunction() { ... yourCode ... } ...meckert der compiler meistens, weil du die funktion vorher nicht bekannt gemacht hast. viele compiler gehen dann davon aus, dass die funktion vom typ INT ist. das meint die fehlermeldung "does not match previous declaration". by default ist jede funktion also INT, findet er jetzt wie oben geschildert eine void-funktion vor, meldet er diesen miss-match. lösung also ganz einfach, die funktion ganz am anfang, dort wo auch die globalen variablen stehen mit typ und eventuell zu übergebenden variablen-typen bekanntmachen (das ist mit prototype einer funktion gemeint), für mein bespiel also: -TOP OF FILE- . . #include .... . void myfunction(void); . . . int main(){ ...... wichtig: wenn nichts an die funktion übergeben wird, dann 'void' in die klammern rein, ansonsten der typ(und nur der typ) der variablen, die werte für diese funktion entgegen nehmen. dieser 'fehler' tritt nach meinem wissen nicht bei jedem compiler auf, wenn, dann liegt es aber oft an oben geschildertem szenario. vielleicht hilft's ja, grüße....
> wichtig: wenn nichts an die funktion übergeben wird, dann 'void' in die > klammern rein, ansonsten der typ(und nur der typ) der variablen, die > werte für diese funktion entgegen nehmen. Kleiner Widerspruch: Ich halte es für durchaus sehr sinnvoll, auch im Funktionsprototypen Variablennamen zu verwenden, da dies die Verwendung der Funktionsparameter dokumentiert. So ist mit einem Blick in die Headerdatei ersichtlich, wie bzw. in welcher Reihenfolge die Parameter zu verwenden sind. - vorausgesetzt, derjenige, der den Funktionsprototypen geschrieben hat, hat sinnvolle Namen verwendet. Manche Quellcodeeditoren verwenden die in Headerdateien gefundenen Prototypen auch für die Eingabeunterstützung ("code completion"), hier ist das Verwenden von Namen für die Parameter auch sehr sinnvoll.
@rufus ich habe im "selbstversuch" mal probiert wie sich das mit dem variablennamen im funktionsprototypen verhält, und es scheint compiler-anhängig zu sein, ob die angabe des variablennamen im prototypen akzeptiert wird oder nicht. mein compiler, den ich 'windows'-anwendungen nutze erlaubt die angabe von vars, der compiler für den mpc(power-pc) meldet hingegen fehler und erwartet lediglich den typ... ..also mal so, mal so, da hilft wohl nur probieren... ;-) grüße
> da hilft wohl nur probieren
Oder mal ein ernstes Wort mit dem Compilerbauer sprechen.
Argumentnamen in einem Prototyp nicht zuzulassen ist nicht
nur gegen den C-Standard, sondern auch bescheuert.
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.