void funktion(void) ?
-
Hallo,
arbeite mich gerade durch ein C++ buch und bin auf folgende zeilen gestoßen:
void funktion(void); // Prototyp
int main(){
...
}void funktion() {
}Meine Frage warum schreibe ich beim Protyp als "Argument" der Funktion nochmal void, dem Compiler scheint es egal zu sein, ob ich
-> void funktion(); oder
-> void funktion(void); als Prototyp schreibe.Wo liegt denn der Sinn und die Funktion des zweiten void?
Gruß Cyberdevil
-
Aus Lesbarkeitsgründen. (Wenn Du solchen Code lesbarer findest; ich zB tue das.)
Vor allem in autogenerierten Dokus kommt sowas IMHO
bool getFoo(void) { return foo; }
oft besser als sowas
bool getBar() { return bar; }
, aber letztlich ist das reine Code-Kosmetik und daher Geschmackssache.
edit: Ich schreibe das übrigens wie man oben bereits erkennen kann nicht nur bei Prototypen sondern auch bei der Implementierung so...
[ Dieser Beitrag wurde am 19.02.2003 um 00:22 Uhr von nman editiert. ]
-
lesbarer? so ein unsinn. mehr text bedeutet immer unlesbarer, wenn der zusaetzliche text keine information enthaelt.
-
nein. hat historische gründe.
a) die gute alte zeit
es waren einmal ein K & ein R, die machten ein supertolle sprache. die war so klasse, daß man sie c nannte. der einfachheit halber rief man funktionen einfach auf, indem man die parameter auf den stack warf und als rückgabewert das annahm, was nach dem funktionsrücksprung in AX war. (oder auf anderen rechnern ein entsprechendes register). die funktion hatte echt selber dafür zu sorgen, aus dem kram auf dem stack was sinnvolles zu machen. der aufrufer hat danach den stack wieder aufgeräumt. man mußte funktionen nicht erst umständlich deklarieren, um sie verwenden zu können. wie man sie aufrief, war ja klar. parameter auf den stack werfen und AX als returnwert verarbeiten. welche parameter in welcher reihenfolge? sowas gehört bei komplizierten dingen ins handbuch und einfache kennt man einfach. und kein kindischer test, ob alles ordnungsgemäß ist.
int quadrat()
int a;
{
return a*a;
}
x=quadrad(5);/*geht*/
x=quadrat();/*geht und macht müll*/man beachte, daß mit dem int a; da nur der funktion selbst mitgeteilt wird, was da los sein soll. was die funktion unter a zu verstehen hat. also welchen speicherplatz man mit a meint und welchen typ das bitmuster da haben soll.
b) ansi-c
und dann haben sich ein paar leute tierisch über ihre eigene inkompetenz geärgert, weil sie allzuoft den funktionen falsche parameter gepusht haben. sie schoben das auf die sprache und sagten "laßt uns aus c ne weibersprache machen". wir machen funktionsdeklarationen. wenn jemand ne funktion deklariert, dann soll der compiler nur noch passende aufrufe fressen. zum glück konnte man noch undeklarierte funktionen nehmen. das ist der grund für die warnung "function with no prototype called". wenn diese warnung fliegt, hat man den heder mit der funktionsdeklaration nicht inkludiert und der compiler geht von der guten alten zeit aus, wirft die parameter auf den stack, ruft die funktion auf, räumt den stack und nimmt AX (oder modernerweise EAX) als returnwert an.
die prototypen haben folgende regeln:
keiner da: alte zeit
rtyp fname(p1typ); fname ist ne funktion, die p1typ nimmt und rtyp zurückgibt
rtyp fname(void); fname ist ne funktion, die NIX nimmt und rtyp zurückgibt
rtyp fname(); fname ist ne funktion, die irgendwas (siehe gute alte zeit) nimmt und rtyp zurückgibt
int quadrat(int a)
{
return a*a;
}
naja, das heimelt schon modern an.
x=quadrad(5);/*geht*/
x=quadrat();/*geht und macht müll*/
aber wenn der prototyp gelesen wurde:
x=quadrad(5);/*geht*/
x=quadrat();/*geht nicht!*/
aber
int f()
{
return 42;
}
mit prototyp
int f();
x=f(1,2,3,"hallo");/*geht*/
schrieb man aber int f(void); ging nix mehr beim aufruf als parameter. es muß kurz nach 1891 gewesen sein (wir hatten damals noch disketten aus holz), da haben die kommunisten das loch entdeckt und ne große propagandawelle zur lähmung der westlichen computerentwicklung gestartet und gesagt: "wenn man komfort in ner sprache hat, muß man den auch echt ausnutzen". sie sagten hier: "jungs, wenn eine funktion nix nehmen soll, dann schreibt (void) dahin, und nicht (), damit ihr compilerfehler kriegt statt laufzeitfehlern!". klar, daß das völlig kindisch ist, aber sie kamen durch damit. jedes c-buch sagt heutzutage, "nimm (void)".c) doch dann erbarmte sich struppi und gab uns c++
er sagte: "jungs, ihr schreibt ja doch immer () statt (void), wir machen das mal so, daß im prototyp () als (void) gilt und die bedeutung ()==irgendwas weg ist". ein jauchzen und tanzen ging duch alle verweichlichten programmiererkreise und nie mehr wurde ein (void) in c++-prototypen gesehen (außer der ersten paar jahrzehnte der umstellung, solange sogenannte fachbücher von autoren geschrieben wurden, die mit c aufgewachsen sind und nach einem 3-tage-fortbildungskurs "oop mit c++" ihr buch nach c++ upgedated haben).ps: ich danke für die recherchen bei Godot und thomas001
-
Sehr interressant. Code Tags rein und in die FAQ!
-
Original erstellt von PeterTheMaster:
lesbarer? so ein unsinn. mehr text bedeutet immer unlesbarer, wenn der zusaetzliche text keine information enthaelt.Beruhig Dich wieder - wenn Du meinen Post gelesen hättest und nicht nur nach Flamepotential gesucht hättest dann hättest Du bemerkt, dass ich Sätze wie "Wenn Du solchen Code lesbarer findest; ich zB tue das.", "...aber letztlich ist das reine Code-Kosmetik und daher Geschmackssache.", "Ich schreibe das..." und so vielseitige Phrasen wie "IMHO" verwendet habe um so einer krassen Missinterpretation meines Posts wie Du sie gerade geliefert hast vorzubeugen.
volkard: Ich war mir nicht darüber im klaren dass es je Unterschiede zwischen foo(void) und foo() gab, wirklich äußerst aufschlussreich, Deine Ausführungen!
-
Original erstellt von volkard:
nein.Doch natürlich. Ich zB lese Quelltext und versuche in auch nachzufollziehen. Etwas, was aber den Ablauf des Programmes nicht beeinflusst, aber trotzdem in Quelltext steht, muss ich auch lesen (um zu überprüfen, ob Informationen drinn stehen). Es lenkt also Aufmerksamkeit auf 'nicht benutzten' Programmtext nicht, wie es sein sollte, auf Informativen. Das ist schade, aber eine übliche Technik, die auch folgende Auswürfe mit sich bringt:
+ Initialisiere alle Variablen mit sinnvollen Werten (0 ist angeblich per Definition sinnvoll) -- hauptsächlich eine C-Krankheit
+ Setzte nach einem delete/free Zeiger auf 0.
+ Pre-/Postkonditionen nach Funktionsaufrufen, die daraus resultieren, dass man die Dokumentation nicht gelesen hat.
+ Sinnleeres Klamen von Ausdrücken zum 'Verdeutlichen'.
+ Explizite Vergleiche auf true/false.
+ uswusfint quadrat()
int a;
{
return a*a;
}Fast. Der Name 'a' wird auch zwischen die () geschrieben. 'int' wurde noch standardmäßig gewählt und musste nicht explizit getippt werden. Ergibt dann:
quadrat (a) { return a * a; }
-
Original erstellt von Lars:
Sehr interressant. Code Tags rein und in die FAQ!ne, FAQ ist nicht für interesante sachen da sondern für sachen die oft gefragt werden
aber ich werde im neuen interesante forum threads urls sammenln und sie in einen FAQ-Thread public machen
-
das gehört in die FAQ. void oder nicht void ist eine Grundsatzfrage.
-
Hi,
PeterTheMaster schrieb:
lesbarer? so ein unsinn. mehr text bedeutet immer unlesbarer, wenn der zusaetzliche text keine information enthaelt.
darf ich daraus folgern, dass du Funktionen grundsätzlich ohne White Spaces in eine Zeile packst und nicht kommentierst?
Ich schreibe auch void bei leeren Parameterlisten, weil ich es schön finde.
ChrisM
-
Daniel E. schrieb:
int quadrat()
int a;
{
return a*a;
}Fast. Der Name 'a' wird auch zwischen die () geschrieben.
Du meinst also, dieser Code ließe sich nicht kompilieren?
-
chris@liet:~% gcc -c -traditional kr.c kr.c: In function `quadrat': kr.c:2: declaration for parameter `a' but no such parameter
So geht's (oder besser ging's):
// unter Ausnutzung von implicit int: quadrat(a) { return a*a; } // mal zur abwechslung mit float: float fquadrat(a) float a; { return a*a; }