Ich wollte eigentlich, daß mir ein Unterprogramm ein array füllt und es leer "call by reference" übergeben. Nun lese ich aber, daß das nur in C++ und nicht in C geht. Kann ich gcc dazu bringen, daß es trotzdem geht? Oder wie kann ich das machen?
Hobbyprogrammierer schrieb: > Ich wollte eigentlich, daß mir ein Unterprogramm ein array füllt und es > leer "call by reference" übergeben. Nun lese ich aber, daß das nur in > C++ und nicht in C geht. Wo/Was hast Du das/da gelesen?
Ein Array kann man in C grundsätzlich nur als call by reference übergeben. Lies mal in deinem C-Buch nach, warum das so ist. Oliver
Pass auf, dass Du die C++ Referenz Übergabe nicht mit Call by Reference verwechselst. In C++
1 | void mach_was(uint16_t& array) |
2 | {
|
3 | |
4 | }
|
In C++ wird "Call by Reference" mit einem Pointer übergeben:
1 | void mach_was(uint16_t* array) |
2 | {
|
3 | |
4 | }
|
Grüsse, René
Jedenfalls hat der Threadstarter von obengenanntem Link im Prinzip das gleiche Problem wie ich.
Ritchie schreibt: 1.8 Arguments - Call by Value One aspect of C functions may be unfamiliar to programmers who are used to some other languages, particulary Fortran. In C, all function arguments are passed ``by value.'' This means that the called function is given the values of its arguments in temporary variables rather than the originals. This leads to some different properties than are seen with ``call by reference'' languages like Fortran or with var parameters in Pascal, in which the called routine has access to the original argument, not a local copy. Also scheint's so ohne weiteres nicht zu gehen.
Hobbyprogrammierer schrieb: > Jedenfalls hat der Threadstarter von obengenanntem Link im Prinzip das > gleiche Problem wie ich. nein, hat er nicht. Du willst ein Feld übergeben; das ist in C immer als CBR übergeben. In dem anderen Thread ging es um andere Variablen (nicht Felder), die sind in C immer CBV.
Bevor (oder damit?) der Arme noch mehr verwirrt wird: Du übergibst dein Array zwar mittels "call per value", aber aber arrays sind in C "Pointer auf das erste Element". d.H. obwohl die Parameterübergabe als "value" erfolgt, hat deine Funktion nacher eine "reference" auf die Array-Inhalte, und kann diese ändern.
Rene H. schrieb: > In C++ wird "Call by Reference" mit einem Pointer übergeben: Natürlich meinte ich beim zweiten Beispiel: In C...... Grüsse, René
Hobbyprogrammierer schrieb: > Ritchie schreibt: > > 1.8 Arguments - Call by Value... Das hilft hier nicht, solange di nicht den restlichen K&R hier reinkopierst, zumindest den Teil mit den Feldern - dort ist es gerade andersrum. Dein Zitat hier ist nur zur Verwirrung gut, sorry.
>d.H. obwohl die Parameterübergabe als "value" erfolgt, hat deine >Funktion nacher eine "reference" auf die Array-Inhalte, und kann diese >ändern. Tatsächlich, es geht. Danke. Jetzt hab ich aber eine neue Anomalie: Byte * Data; ... printf("%02i: %02X\t\t", i*8+j, Data); ... Jetzt sollte eigentlich (der Logik nach was ich heute gelernt habe )die Adresse von Data angezeigt werden, oder? Stattdessen wird (was durchaus wünschenswert ist) der Inhalt auf den der Zeiger zeigt, angezeigt. Oh Mann, das schwächt.
Klaus Wachtler schrieb: > Das hilft hier nicht, solange di nicht den restlichen K&R hier > reinkopierst, zumindest den Teil mit den Feldern - dort ist es gerade > andersrum. Nein. Auch da wird by value übergeben. Aber eben ein Zeiger.
Hobbyprogrammierer schrieb: > Jetzt sollte eigentlich (der Logik nach was ich heute gelernt habe )die > Adresse von Data angezeigt werden, oder? Für Zeiger gibt es bei printf den Formatspecifier %p. Ein Zeiger ist kein (unsigned) int
Dann ist es formaljuristisch auf allen Plattformen korrekt. Solange aber sizeof (int) == sizeof (int *) ist, funktioniert die --unsaubere-- Variante auch. Den Irrtum hat der Hobbyprogrammierer ja auch schon selbst bemerkt.
Stefan Rand schrieb: > Klaus Wachtler schrieb: >> Das hilft hier nicht, solange di nicht den restlichen K&R hier >> reinkopierst, zumindest den Teil mit den Feldern - dort ist es gerade >> andersrum. > > Nein. Auch da wird by value übergeben. Aber eben ein Zeiger. Darüber kann man jetzt philosphieren. Daß ein Zeiger übergeben wird, ist sicher richtig und das sollte inzwischen auch jeder verstanden haben. Ein Zeiger auf etwas ist aber nun mal auch eine Referenz (auch wenn in C++ eine Referenz im Quelltext dann wieder anders aussieht, aber hier geht es ja um C). Was das Feld angeht, wird es eben damit also per Referenz und nicht per Wert übergeben. Daß dieses technisch gelöst ist, indem ein Zeiger auf das erste Element übergeben wird, ist ja kein Widerspruch. Bei C++ sind Referenzen ja intern wieder ebenso realisiert, nur daß man den zugehörigen Zeiger nicht direkt sieht. Für den TO ist es nach wie vor so, daß er beim Aufrufer sein Feld in die Parameterliste schreibt und die Funktion die Elemente des Originalfeldes setzen kann, nicht die Elemente einer Kopie des Feldes (wie es bei call by value der Fall wäre, also bei nicht-Array-Parametern).
Klaus Wachtler schrieb: > Darüber kann man jetzt philosphieren. Eigentlich nicht. call-by-value und call-by-reference sind Sprachfeatures. Und C hat letzteres schlicht nicht. > Was das Feld angeht, wird es eben damit also per Referenz und nicht per > Wert übergeben. Das Feld wird eben nicht übergeben. In abstrakt-wolkiger Denkweise: klar. Aber soweit wir hier über C-Programmierung reden und nicht über irgendwelche Designdokumente wird da ein Zeiger übergeben. Kein Feld. Und das sollte man auf dieser Ebene besser auch nicht vermischen. Denn das führt bei Leuten, die dieses C-eigene, völlig unintuitive Prinzip nicht komplett verdaut haben, immer wieder zu Mißverständnissen.
Stefan Rand (srand) schrieb: Klaus Wachtler schrieb: >> Darüber kann man jetzt philosphieren. > Eigentlich nicht. Eigentlich schon. > call-by-value und call-by-reference sind Sprachfeatures. Und C hat > letzteres schlicht nicht. Es hat aber einen Meachanismus, der genau das gleiche bewirkt. Manche Bücher unterscheiden deshalb nicht bei call-by-reference zwischen C und C++ siehe Beispielsweise hier http://openbook.galileocomputing.de/c_von_a_bis_z/012_c_zeiger_006.htm "In solch einem Fall bietet es sich an, statt der Variablen radius einfach nur die Adresse der Variablen als Argument zu übergeben. Die Übergabe von Adressen als Argument einer Funktion wird call-by-reference genannt. Das Prinzip sehen Sie im abgeänderten Programmbeispiel:"
Hobbyprogrammierer schrieb: >>d.H. obwohl die Parameterübergabe als "value" erfolgt, hat deine >>Funktion nacher eine "reference" auf die Array-Inhalte, und kann diese >>ändern. > > Tatsächlich, es geht. Das ist übrigens ein Grund warum es "const" gibt, damit Du dem Compiler sagen kannst dass Du zwar den Pointer auf das erste Array-Element übergibst, aber nicht willst dass darüber dann die Array-Elemente (versehentlich) modifiziert werden.
Hobbyprogrammierer schrieb: > Byte * Data; > ... > printf("%02i: %02X\t\t", i*8+j, Data); Byte *Data; -> Ist ein Pointer (Zeiger) der auf den Anfang(Adresse) der Speicherzellen von Data zeigt. Im printf wird die Adresse der Speicherzelle von Data ausgegeben. Besseres Beispiel, vielleicht verständlicher(?):
1 | char *bp; /* Buffer pointer , zeigt jetzt ins nirgendwo */ |
2 | |
3 | bp = (char *)malloc(sizeof(char)*10); /* hat jetzt die Startadresse |
4 | die von malloc geliefert wurde, oder NULL.
|
5 | Wir nehmen mal an, dass malloc != NULL geliefert hat.*/
|
6 | |
7 | printf("%x", bp); /* Gibt die Adresse von bp aus */ |
8 | |
9 | *bp = 'A'; /* Schreibt das Zeichen 'A' an die Startadresse von bp*/ |
10 | *(bp+1) = NULL; /* String terminieren */ |
11 | printf("%s",*bp); /* Gibt den Inhalt von bp aus */ |
Hoffe, dass ich etwas zur Verwirrung beitragen konnte.
MAD schrieb: > *bp = 'A'; /* Schreibt das Zeichen 'A' an die Startadresse von bp*/ > *(bp+1) = NULL; /* String terminieren */ > printf("%s",*bp); /* Gibt den Inhalt von bp aus */ > > Hoffe, dass ich etwas zur Verwirrung beitragen konnte. Ja, das konntest du ganz gewiss ;-) Mal abgesehen davon, dass das String-Endezeichen offiziell nicht NULL, sondern '\0' heißt (was immerhin durch einen impliziten Cast vom Compiler wieder zurechtgebogen wird), tut die Zeile mit dem printf doch recht seltsam Dinge (einfach mal ausprobieren).
MAD schrieb: > > printf("%02i: %02X\t\t", i*8+j, Data); > Byte *Data; -> Ist ein Pointer (Zeiger) der auf den Anfang(Adresse) der > Speicherzellen von Data zeigt. Nein. Data zeigt nicht "auf den Anfang der Speicherzellen von Data". > Im printf wird die Adresse der Speicherzelle von Data ausgegeben. Nein. Hier wird der Inhalt von Data ausgegeben. Um die Adresse der Speicherzelle von Data auszugeben, müsste das hier gemacht werden:
1 | printf("%08X", &Data); |
(statt %x sollte korrekterweise %p verwendet werden)
Im hier gewählten Kontext aber möchte niemand die Adresse von Data
wissen, da Data selbst ein Pointer ist und dieser interessant ist.
> printf("%x", bp); /* Gibt die Adresse von bp aus */
Gleicher Fehler. Du verwechselst Pointer mit dem, worauf sie zeigen.
Hier wird nicht die Adresse von bp ausgegeben, sondern die Adresse
dessen, worauf bp zeigt -- also der Inhalt von bp.
Zu Pointern, Adressen, ... hilft vielleicht folgendes Video: http://et-tutorials.de/3368/pointer-in-c/
Rufus Τ. Firefly schrieb: > Dann ist es formaljuristisch auf allen Plattformen korrekt. > > Solange aber sizeof (int) == sizeof (int *) ist, funktioniert die > --unsaubere-- Variante auch. Allerdings haben Pointer auf manchen Plattformen etwas spezielle Schreibweisen, die %p berücksichtigen kann, %i aber nicht. Außerdem werden bei %i die Werte dezimal angezeigt und bei hohen Adressen ggf. auch negativ. Klaus Wachtler schrieb: > Bei C++ sind Referenzen ja intern wieder ebenso realisiert, nur daß man > den zugehörigen Zeiger nicht direkt sieht. Sie können so implementiert sein, müssen es aber nicht. Gelegenheitsprogrammierer schrieb: > Stefan Rand (srand) schrieb: > > Klaus Wachtler schrieb: >>> Darüber kann man jetzt philosphieren. > >> Eigentlich nicht. > > Eigentlich schon. Philosophieren kann man darüber. Wenn man aber doch lieber technisch als philosophoisch diskutieren will, bekommt man bei Übergabe eines Arrays aus int an eine Funktion einen Zeiger auf einen int und nicht eine Referenz auf ein Array aus int. >> call-by-value und call-by-reference sind Sprachfeatures. Und C hat >> letzteres schlicht nicht. > > Es hat aber einen Meachanismus, der genau das gleiche bewirkt. Daß es das eben nicht tut, sieht man schon daran, daß sizeof innerhalb der Funktion die Größe eines Zeigers und nicht die des Arrays liefert. > Manche Bücher unterscheiden deshalb nicht bei call-by-reference zwischen > C und C++ siehe Beispielsweise hier > > http://openbook.galileocomputing.de/c_von_a_bis_z/012_c_zeiger_006.htm > > "In solch einem Fall bietet es sich an, statt der Variablen radius > einfach nur die Adresse der Variablen als Argument zu übergeben. Die > Übergabe von Adressen als Argument einer Funktion wird call-by-reference > genannt. Das Prinzip sehen Sie im abgeänderten Programmbeispiel:" Es ist nicht automatisch richtig, nur weil's in irgendeinem Buch steht. Zur Vereinfachung kann man es auch anfangs auch abstrahiert als "call-y-reference" bezeichnen, aber richtig ist das eigentlich nicht.
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.