Hallo, Ich habe eine Frage zu Funktionsdefinitionen in C: Die Syntax sieht ja so aus: 1. Rückgabetyp 2.Funktionsname(Parameter) { /* Anweiungsblock mit Anweiungen */ } 1.Also als Rückgabewert kann jeder beliebige Datentyp genommen werden 2.Der Funktionsname muss eindeutig sein, mit der man die Funktion von einem anderen Programmteil aus aufrufen kann. Ich verstehe nicht, was man als Parameter angeben muss, und wozu man diese Parameter überhaupt braucht. Auch wie das mit dem Rückgabetyp so richtig funktioniert, weiß ich nicht.Ich würde mich über zahlreiche Beschreibungen freuen! Vielen Dank! Gruss Daniel -- clusterix.perl@gmx.de
Hallo Daniel,
Natürlich kannst du komplett ohne Rückgabeparameter auskommen, genau dann,
wenn du TONNEN von Globalen Variablen anlegst. (In diesem Falle, brauchst du
natürlich auch keine Parameter.
Aber nehmen wir mal an, du hast einen Funktion, deren Rückgabewert du dir
nicht das ganze Programm über merken möchtest, in so einem Fall, fragst du
den Rückgabewert ab, reagierst entsprechend und vergisst ihn wieder.
Ferner lassen sich Rekursive funktionen nur schreiben, wenn man Parameter und
Rückgabewert benutzt. (Rekursion -> siehe Vollständige Induktion aus der
Mathematik)
Also, um genau zu sein:
Globale Variablen landen auf dem Programmheap,
Lokale Variablen, Parameter landen auf dem Stack
Parameter und lokale Variablen sind nach verlassen der Funktion meist nicht
mehr gültig (Ausnahmen sind von Pointern referenzierte Variablen oder aber
eben Referenzen, wenn man von C++ spricht)
Aber hier ein kleines Beispiel:
(Bitte beachten, dass int sehr schnell überläuft)
<<< snippit <<<
#include
snippit >>>
natürlich kannst du jetzt sagen: "Das kann ich aber iterativ viel schneller." Klar, aber das ist ein einfaches Beispiel. Denk dir einfach eine Funktion, die einen Weg durch ein Labyrinth berechnen soll. (Backtracking) Aehhh, ich glaub, das führt jetzt zu weit. Ich empfehle dir mal ein C/C++ Buch kaufen und zu lesen Mein ganz persönlicher Favorit ist: Knuth: The Art of Computer Programming Aber erstens ist der sehr teuer, zweitens nur in Englisch und drittens schwere Kost. Wenn du bisher BASIC Programmiert hast, wirst du die Notwendigkeit nicht so schnell einsehen. Als Tip: Schau dir mal JAVA an: Java kennt keine Globalen Variablen! Ach so, zum Rückgabewert: In C kommt dieser, sofern er passt in einem oder mehreren Prozessorregistern zurück. Das ist der Grund, warum du auch keine Strukturen als Rückgabeparameter nehmen kannst sondern nur Referenzen oder Pointer. Ich hoffe, du konntest damit jetzt was anfangen. - Arndt Am Sonntag, 22. Juni 2003 11:58 schrieb Daniel Feist:
Hallo, Ich habe eine Frage zu Funktionsdefinitionen in C: Die Syntax sieht ja so aus:
1. Rückgabetyp 2.Funktionsname(Parameter) { /* Anweiungsblock mit Anweiungen */ }
1.Also als Rückgabewert kann jeder beliebige Datentyp genommen werden
2.Der Funktionsname muss eindeutig sein, mit der man die Funktion von einem anderen Programmteil aus aufrufen kann.
Ich verstehe nicht, was man als Parameter angeben muss, und wozu man diese Parameter überhaupt braucht. Auch wie das mit dem Rückgabetyp so richtig funktioniert, weiß ich nicht.Ich würde mich über zahlreiche Beschreibungen freuen! Vielen Dank!
Gruss Daniel -- clusterix.perl@gmx.de
Hallo, On Sun, 22 Jun 2003 at 12:27 (+0200), Arndt Stedler wrote:
Wenn du bisher BASIC Programmiert hast, wirst du die Notwendigkeit nicht so schnell einsehen. Als Tip: Schau dir mal JAVA an: Java kennt keine Globalen Variablen!
Java kennt statische Klassenvariablen. Wenn Du nur in einer Klasse programmierst (in der, in der sich die main-Methode befindet), jede Funktion statisch machst und mit statischen Klassenvariablen arbeitest, hast Du das selbe in gruen. Sowas wie eine globale Varialbe in C++ (wo es ja auch Klassen gibt) und globale Funktionen gibt es allerdings in Java nicht.
Ach so, zum Rückgabewert: In C kommt dieser, sofern er passt in einem oder mehreren Prozessorregistern zurück. Das ist der Grund, warum du auch keine Strukturen als Rückgabeparameter nehmen kannst sondern nur Referenzen oder Pointer.
Stimmt so nicht. Auch in C kannst Du eine struct und eine union zurueckgeben (nein, keinen Zeiger darauf), allerdings ist das modernes C und kein altes C. Auch der Zuweisungsoperator ist auf Strukturen definiert. Ein saudummes Beispiel: struct zeit { int stunde; int minute; int sekunde; }; struct zeit demo () { struct zeit meinezeit = { 1, 2, 3 }; return meinezeit; } int main (int argc, char *argv[]) { struct zeit nocheinezeit; nocheinezeit = demo(); printf("Std: %d\nMin: %d\nSek: %d\n", nocheinezeit.stunde, nocheinezeit.minute, nocheinezeit.sekunde); return 0; } Gruss, Bernhard -- _________ http://www.bwalle.de _________________________________________________ "Nachrichtensprecher fangen stets mit 'Guten Abend' an und brauchen dann 15 Minuten, um zu erklären, dass es kein guter Abend ist." -- Rudi Carrell
Hallo Bernhard, Also ok, ich gebe zu, ich bin ein Dinosaurier, was C/C++ angeht, denn eigentlich nutze ich meinen Compiler mehr oder weniger als Super-Macro-Assembler ;-) Aber erklär mir doch mal, wie ein solcher struct zurückgebgeben wird. Denn a) er passt ggf. nicht (bei einem 80X86 Prozessor) in die Register b) Wenn man in Assembler den Stack erst nachher aufräumt, kann der Aufrufer natürlich daher seinen Rückgabewert bekommen. Wobei mir aber noch nicht klar ist, wie dass dann gehen soll. Kannst du mal einen Assembler-output davon erzeugen? (Assembler Egal) Würde mich mal interessieren. Es sei denn, du hast das unten genannte Beispiel durch einen C++ Compiler gescheucht, dann verstehe ich das ganze, denn die neuen C++ Compiler behandeln struct und class identisch und somit hast du keinen struct im eigentlichen sinne sondern eine class und damit übergibt der Compiler (mal wieder) eine Referenz. Oder liege ich da falsch? (Ich muss mir das mal anschauen, wenn ich zeit habe) Zu Java: Erwischt, bin halt ein Java-Hasser ;-) Nein, habe mich nur Rudimentär mit Java auseinander gesetzt. Aber alles als statisch zu deklarieren ist vielleicht auch nicht das Grüne vom Ei... ;-) - Arndt
Am Sonntag, 22. Juni 2003 13:20 schrieb Bernhard Walle: Hallo,
On Sun, 22 Jun 2003 at 12:27 (+0200), Arndt Stedler wrote:
Wenn du bisher BASIC Programmiert hast, wirst du die Notwendigkeit nicht so schnell einsehen. Als Tip: Schau dir mal JAVA an: Java kennt keine Globalen Variablen!
Java kennt statische Klassenvariablen. Wenn Du nur in einer Klasse programmierst (in der, in der sich die main-Methode befindet), jede Funktion statisch machst und mit statischen Klassenvariablen arbeitest, hast Du das selbe in gruen. Sowas wie eine globale Varialbe in C++ (wo es ja auch Klassen gibt) und globale Funktionen gibt es allerdings in Java nicht.
Ach so, zum Rückgabewert: In C kommt dieser, sofern er passt in einem oder mehreren Prozessorregistern zurück. Das ist der Grund, warum du auch keine Strukturen als Rückgabeparameter nehmen kannst sondern nur Referenzen oder Pointer.
Stimmt so nicht. Auch in C kannst Du eine struct und eine union zurueckgeben (nein, keinen Zeiger darauf), allerdings ist das modernes C und kein altes C. Auch der Zuweisungsoperator ist auf Strukturen definiert.
Ein saudummes Beispiel:
struct zeit { int stunde; int minute; int sekunde; };
struct zeit demo () { struct zeit meinezeit = { 1, 2, 3 }; return meinezeit; }
int main (int argc, char *argv[]) { struct zeit nocheinezeit;
nocheinezeit = demo(); printf("Std: %d\nMin: %d\nSek: %d\n", nocheinezeit.stunde, nocheinezeit.minute, nocheinezeit.sekunde);
return 0; }
Gruss, Bernhard
-- _________ http://www.bwalle.de _________________________________________________ "Nachrichtensprecher fangen stets mit 'Guten Abend' an und brauchen dann 15 Minuten, um zu erklären, dass es kein guter Abend ist." -- Rudi Carrell
Hallo, On Sun, 22 Jun 2003 at 17:31 (+0200), Arndt Stedler wrote:
Aber erklär mir doch mal, wie ein solcher struct zurückgebgeben wird. Denn a) er passt ggf. nicht (bei einem 80X86 Prozessor) in die Register b) Wenn man in Assembler den Stack erst nachher aufräumt, kann der Aufrufer natürlich daher seinen Rückgabewert bekommen. Wobei mir aber noch nicht klar ist, wie dass dann gehen soll. Kannst du mal einen Assembler-output davon erzeugen? (Assembler Egal) Würde mich mal interessieren.
Ich weiss es nicht. Mit Assembler kenne ich mich ueberhaupt nicht aus. ---------------------------------------------------- .file "test.c" .version "01.01" gcc2_compiled.: .text .align 4 .globl demo .type demo,@function demo: pushl %ebp movl %esp,%ebp subl $24,%esp movl 8(%ebp),%eax movl $1,-12(%ebp) movl $2,-8(%ebp) movl $3,-4(%ebp) movl -12(%ebp),%edx movl %edx,(%eax) movl -8(%ebp),%edx movl %edx,4(%eax) movl -4(%ebp),%edx movl %edx,8(%eax) jmp .L2 .L2: movl %eax,%eax leave ret $4 .Lfe1: .size demo,.Lfe1-demo .section .rodata .LC0: .string "Std: %d\nMin: %d\nSek: %d\n" .text .align 4 .globl main .type main,@function main: pushl %ebp movl %esp,%ebp subl $24,%esp leal -12(%ebp),%eax addl $-12,%esp pushl %eax call demo addl $12,%esp movl -4(%ebp),%eax pushl %eax movl -8(%ebp),%eax pushl %eax movl -12(%ebp),%eax pushl %eax pushl $.LC0 call printf addl $16,%esp xorl %eax,%eax jmp .L3 .p2align 4,,7 .L3: leave ret .Lfe2: .size main,.Lfe2-main .ident "GCC: (GNU) 2.95.4 20011002 (Debian prerelease)" ---------------------------------------------------- Wenn Du das dann noch fuer Assembler-unkundige wie mich interpretieren koenntest waere ich Dir sehr dankbar.
Es sei denn, du hast das unten genannte Beispiel durch einen C++ Compiler gescheucht, dann verstehe ich das ganze, denn die neuen C++ Compiler behandeln struct und class identisch und somit hast du keinen struct im eigentlichen sinne sondern eine class und damit übergibt der Compiler (mal wieder) eine Referenz. Oder liege ich da falsch? (Ich muss mir das mal anschauen, wenn ich zeit habe)
Nein, es ist kein C++ Compiler. Es ist gcc. Und ich habe auch mal gelesen, dass modernes C (C99, nicht C++) sowas kann. Nur wie das in C++ funktioniert kapiere ich jetzt auch nicht, was heisst "uebergibt eine Referenz". Ein Zeiger im eigentlichen Sinne kann's ja nicht sein, sonst muesste man das Rueckgabeobjekt ja mit delete wieder freigeben. Stattdessen wird ja das Objekt auf dem Stack abgelegt und der Copy-Konstruktor aufgerufen.
Zu Java: Erwischt, bin halt ein Java-Hasser ;-) Nein, habe mich nur Rudimentär mit Java auseinander gesetzt. Aber alles als statisch zu deklarieren ist vielleicht auch nicht das Grüne vom Ei... ;-)
Habe ich auch nicht behauptet. Gruss, Bernhard -- _________ http://www.bwalle.de _________________________________________________ Applaus: Rauschmittel, unter dessen Einwirkung Politiker sich zu den seltsamsten Erklärungen verleiten lassen. -- Ron Kritzfeld
Daniel Feist
Ich verstehe nicht, was man als Parameter angeben muss,
Angeben musst du gar nichts. Wenn die Funktion keine Parameter braucht, gibt man 'void' als einzigen Parameter an.
und wozu man diese Parameter überhaupt braucht.
Eine Funktion braucht Daten, mit denen sie hantieren soll. So erwartet z.B. die Funktion sqrt(double) den Wert, aus welchem sie die Wurzel ziehen soll. Wie willst du sonst einer Funktion Werte übergeben? Über globale Variablen? Das macht nur selten Sinn.
Auch wie das mit dem Rückgabetyp so richtig funktioniert, weiß ich nicht.
Was ist daran unverständlich? Der Rückgabetyp ist der Typ des Argumentes, welches eine Funktion zurückliefert. Also double sqrt(double val) besagt, dass die Funktion eine Fliesskommazahl doppelter Genauigkeit zurückliefert. Philipp
participants (4)
-
Arndt Stedler
-
Bernhard Walle
-
Daniel Feist
-
Philipp Thomas