> Es genügt
Rein rechtlich: ja.
Gute Idee ist es aber keine.
Zum Thema Prototypen:
Das Ur-C (K&R C) brauchte die noch nicht. Man konnte, musste
aber nicht. Es trat dann die 'implizit-int' Rgel in Kraft.
D.h. der Return-Typ der Funktion wurde implizit ls int
angenommen. Die Datentypen der Argumente konnte sich der
Compiler ja aus em Funktionsaufruf ableiten.
Das brachte dann so lustige, und für den unbedarften Programmierer
ausserst schwer zu findende, Fehler, wie:
1 | int main()
|
2 | {
|
3 | double x;
|
4 |
|
5 | x = sin(0);
|
6 | }
|
und jetzt such mal schön :-)
* Da kein Prototyp für sin vorhanden ist, geht der Compiler
davon aus, dass die Funktion einen int returned. Tut sie
aber nicht. sin liefert einen double. D.h. die Funktion
legt einen double für den Rückgabemechanismus bereit, der
Aufrufer hingegen behandelt die Bytes als ob sie ein int wären.
* Da kein Prototyp für sin vorhanden ist, muss der Compiler die
Argumenttypen aus dem Aufruf ableiten. Im obigen Fall kommt er
zum Schluss, dass sin wohl einen int nehmen wird, da ja 0 ein
int darstellt. D.h. der Compiler baut den Aufruf so, dass als
Argument die Bytes für einen int übergeben werden.
Nur: sin nimmt einen double! d.h. die Implementierung für sin
nimmt die Bytes die es kriegen kann und interpretiert sie
als double.
* mal davon abgesehen, dass sizeof(int) meistens nicht gleich
sizeof(double) ist, haben int und double aber auch völlig andere
Repräsentierungen als Bytes, so dass hier ein heilloses Durcheinander
ensteht.
Abhilfe schafft nur ein Prototyp:
1 | double sin(double);
|
2 |
|
3 | int main()
|
4 | {
|
5 | double x;
|
6 |
|
7 | x = sin(0);
|
8 | }
|
Jetzt weiss der Compiler, dass es eine Funktion namens 'sin'
gibt (könnte ja auch ein Tippfehler sein), dass die Funktion
einen double erwartet und einen double zurückliefert.