Hallo,
habe mal eine Frage.
Wenn ich im AVR-Studio in C eine Funktion aus einer Funktion aufrufe,
die von der Main-Funktion aufgerufen wurde, erhalte ich beim Compilieren
folgenden Hinweis (und danach noch ein paar andere, die dazu gehören):
>>warning: implicit declaration of function 'y'
Hier noch der schematische Aufbau:
>int main(void){...} --> void x(){...} --> void y(){...}
Bei built selber gibt keine weiteren Fehlermeldungen und der Controller
funktioniert nach dem Flashen, wie er soll.
Mich würde trotzdem interessieren, warum hier die Warnung erscheint?
Außerdem würde mich interessieren, ob man Funktionen grundsätzlich mit
"return" beenden sollte oder ob es prinzipiel egal ist?
Nachtrag, es soll natürlich heißen:
Bei built selber gibt es keine weiteren Fehlermeldungen und der
Controller funktioniert nach dem Flashen, wie er soll.
fragendermensch schrieb:> Hallo,>> habe mal eine Frage.>> Wenn ich im AVR-Studio in C eine Funktion aus einer Funktion aufrufe,> die von der Main-Funktion aufgerufen wurde, erhalte ich beim Compilieren> folgenden Hinweis (und danach noch ein paar andere, die dazu gehören):>>>>warning: implicit declaration of function 'y'
"implicit declaration" bedeutet immer, dass eine Funktion benutzt wurde
(aufgerufen wurde), noch ehe der COmpiler die Funktion selber, entweder
als Funktions-Definition oder als Protoyp) zu Gesicht bekommen hat.
Das ist also eine reine Frage der Reihenfolge der Funktionen in deinem
File, bzw. ob du Prototypen hast oder nicht.
Lies dein C-File von oben nach unten durch und überleg dir was du machen
musst, damit beim Durchlesen des Codes es nie zu der Situation kommt,
dass du eine Funktion aufrufen willst, noch ehe die Funktion deklariert
ist.
> Mich würde trotzdem interessieren, warum hier die Warnung erscheint?
Weil der Compiler dann Standard-Annahmen treffen muss. Die können
richtig sein, können aber auch falsch sein.
> Außerdem würde mich interessieren, ob man Funktionen grundsätzlich> mit "return" beenden sollte oder ob es prinzipiel egal ist?
falsche Frage.
Die richtige Frage lautet: wann brauche ich auf jeden Fall ein return?
Grundsätzlich sollte man alle Warnungen erst nehmen und beseitigen. Es
gibt nur einige wenige Fälle wo das nicht möglich ist, aber die sind für
Anfänger in der Regel unwichtig.
>Außerdem würde mich interessieren, ob man Funktionen grundsätzlich mit>"return" beenden sollte oder ob es prinzipiel egal ist?
Das kommt auf die Funktion an. Wenn sie einen Rückgabewert hat, dann
muss ein return mit einem Ausdruck enthalten sein. Wenn der Rückgabewert
void ist, dann kannst Du das return weglassen. Allerdings wird das
teilweise als schlechter Stil betrachtet.
In der Datei, die die main enthält, mache ich es immer so, dass ich die
Funktionsprototypen vor die main schreibe, aber die Funktionen selber
dahinter.
1
voidx();
2
voidy();
3
4
intmain(){...}
5
6
voidx(){...}
7
voidy(){...}
Dann kennt der Compiler die Funktionen und kann sie richtig benutzen,
aber bis auf eine kurze Liste mit Funktionsprototypen steht die main
ganz oben. So sieht man auf den ersten Blick die main und muss nur
suchen, wenn man sich eine Funktion genauer ansehen will.
Hmm schrieb:> Dann gucke ich jetzt Simpsons.
Auf ProSieben kommen die etwa um zehn nach sieben.
Karl Heinz Buchegger schrieb:> Lies dein C-File von oben nach unten durch und überleg dir was du machen> musst, damit beim Durchlesen des Codes es nie zu der Situation kommt,> dass du eine Funktion aufrufen willst, noch ehe die Funktion deklariert> ist.
Hallo,
herzlichen Dank für die schnellen und vielen Antworten!!!
Habe jetzt die Reihenfolge der Funktionen im Programmfile geändert, nun
wird keine Warnung mehr angezeigt.
Was genau versteht man unter einem Funktionsprototypen?
Viele Grüße
Dussel schrieb:
...
>> int main(){...}>> void x(){...}> void y(){...}Dann kennt der Compiler die Funktionen und kann sie richtig
benutzen,
> aber bis auf eine kurze Liste mit Funktionsprototypen steht die main> ganz oben. So sieht man auf den ersten Blick die main und muss nur> suchen, wenn man sich eine Funktion genauer ansehen will.
Super, das mache ich beim nächsten mal auch so, Danke! Bisher landet die
Main-Funktion bei mir immer gaaaanz unten :-)
fragendermensch schrieb:> Was genau versteht man unter einem Funktionsprototypen?
2 Dinge.
Das erste bedeutet, dass du ganz dringend ein C-Buch brauchst
Das zweite: Den Funktionskopf, in dem man festlegt, wie die Funktion
nach aussen aussieht.
hast du eine Funktion
double CalcMwst( double Preis )
{
return 0.2 * Preis;
}
dann ist
double CalcMwst( double );
der zugehörige Protoyp. Alles was ein Aufrufer von der Funktion wissen
muss, um sie korrekt benutzen zu können. Und das ist
* wie heißt die Funktion
* welche und wieviele Argumente nimmt sie?
Welche Datentypen haben die Argument?
* welchen Returntyp hat die Funktion
Aus praktischen Gründen ist es sinnvoll, die Namen der Argumente mit in
den Protoypen aufzunehmen
double CalcMwst( double Preis );
Karl Heinz Buchegger schrieb:> ... der zugehörige Protoyp. Alles was ein Aufrufer von der Funktion wissen> muss, um sie korrekt benutzen zu können. Und das ist> * wie heißt die Funktion> * welche und wieviele Argumente nimmt sie?> Welche Datentypen haben die Argument?> * welchen Returntyp hat die Funktion>> Aus praktischen Gründen ist es sinnvoll, die Namen der Argumente mit in> den Protoypen aufzunehmen> double CalcMwst( double Preis );
Danke für die Erklärung! Im Grunde ist es von der Form her (ähnlich) wie
der Funktionsaufruf selber, nur, dass man es "frei" vor die Main- und
andere Funktionen schreiben kann!?!
Karl Heinz Buchegger schrieb:> Das erste bedeutet, dass du ganz dringend ein C-Buch brauchst
Wird beherzigt!
fragendermensch schrieb:> Danke für die Erklärung! Im Grunde ist es von der Form her (ähnlich) wie> der Funktionsaufruf selber,
Nicht wie der Funktions-AUFRUF sondern wie die Funktion selber. Nur eben
ohne die Implementierung. Der Prototyp enthält alles was man wissen
muss, um zu entscheiden, ob ein Aufruf
1
intmain()
2
{
3
doublei,j=5;
4
5
i=CalcMwst(j,8);
6
}
korrekt sein kann (der hier kann nicht korrekt sein, weil die Funktion
ja keine 2 Argumente nimmt), bzw. welche Umwandlungen automatisch
vorgenommen werden müssen (sofern dies möglich ist)
1
intmain()
2
{
3
intj;
4
5
j=CalcMwst(6);
6
}
der Integer 6 muss zum Aufruf der Funktion in einen double gewandelt
werden und das Funktionsergebnis muss von einem double zu einem int
gewandelt werden.
Damit man das erkennen kann, reicht es völlig aus, wenn man ...
1
doubleCalcMwst(double);
... weiß - vulgo den Funktionsprotoypen. Und mehr als dieses Wissen
benötigt der Compiler nicht, um den Aufruf auf Korrektheit zu prüfen und
korrekt durchzuführen.
Wenigstens haben die Österreicher noch nicht die deutsche Unsitte
übernommen, nach jedem halben Satz Klopapier und Achselschweiss zu
verkaufen. Das und Almdudlder und Salzburger Nockerln läßt mich manchmal
von der Auswanderung nach Österreich träumen.