Hans schrieb:> void test(unsigned char array[])> {> array = testArray;> }
was soll das auch bewirken?
du änderst damit eine Lokale Variabel - mehr nicht. Damit das
funktioniert muss man ein zeiger auf ein Array übergeben.
> unsigned char mainArray[5];
das kann aber sowieso nicht geändert werden, weil es kein Pointer
sondern wirklich ein Array ist.
Hans schrieb:> Array werden doch nie mit "call by value" übergeben, oder nicht?
C kennt nur call by value, nichts anderes.
Wie oft willst du das noch hören?
> Dann müsste sich dies doch wie ein Pointer verhalten..
Eben nicht.
Hans schrieb:> Array werden doch nie mit "call by value" übergeben, oder nicht?> Dann müsste sich dies doch wie ein Pointer verhalten..
ja machen sie ja auch.
1
voidtest(int*i)
2
{
3
i=(int*)0x1234;
4
}
ändert auch nichts, für den Aufrufer. Genau wie bei dir.
Peter II schrieb:> Hans schrieb:>> Hmm, mit Pointer habe ich es auch schon probiert. Funktioniert auch>> nicht.>> du brauchst ein pointer auf ein pointer>>
1
>voidtest(unsignedchar*Array[])
2
>
Nein. bracuht er nicht.
Er braucht die Erkenntnis, dass Arrays nicht als ganzes zuweisbar sind.
1
voidtest(unsignedchararray[])
2
{
3
array[0]=testArray[0];
4
array[1]=testArray[1];
5
array[2]=testArray[2];
6
}
und das die vermaledeite Parametersyntax
1
voidtest(unsignedchararray[])
nichts anderes als syntaktischer Zucker für
1
voidtest(unsignedchar*array)
darstellt. Die beiden Formen sind nur unterschiedliche Schreibweisen für
dasselbe.
Hans schrieb:> Michael schrieb:>> C kennt nur call by value, nichts anderes.>> Was?!> http://openbook.galileocomputing.de/c_von_a_bis_z/012_c_zeiger_006.htm
Ändert nichts.
Der Zeiger wird per value übergeben.
Das man den Zeiger dazu benutzen kann, um mit seiner Hilfe auf die
Variable des Aufrufers durchzugreifen, ändert daran nichts, das der
Zeiger selbst per value übergeben werden. Der Zeiger ist in diesem Sinne
quasi ein Hilfsmittel, um damit call-by-reference zu simulieren. Echtes
call-by-reference funktioniert aber syntaktisch anders.
AM Beispiel C++
1
voidfoo(int&i)
2
{
3
i=5;
4
}
hier ist i eine Referenz. Innerhalb der Funktion benutzt du als ganz
normale Variable, der du etwas zuweisen kannst. Da diese Referenz beim
Aufruf an die Variable des Aufrufers gebunden wird, ändert damit eine
Zuweisung an i die Variable des Aufrufers.
Das wäre ein echter call-by-Referenz. Das dieser Mechanismus unter der
Decke vom Compiler mittels Zeiger realisiert wird, ist ein Detail, das
dich als C++ Programmierer nicht zu kümmern braucht.
Ganz anders in C. Dort gibt es keinen echten call-by-refence. Er wird
dadurch simuliert, das man der Funktion einen Zeiger auf die Variable
des Aufrufers gibt
1
voidfoo(int*i)
2
{
3
*i=5;
4
}
5
6
intmain()
7
{
8
intj;
9
10
foo(&j);
11
}
aber schon alleine dadurch, dass hier spezielle Syntax notwendig ist, um
die Adresse der Variable des Aufrufers zu bestimmen, bzw. in der
Funktion die Derferenzierung vorzunehmen, zeigt schon, das hier kein
echter call-by-reference vorliegt. Denn bei einem echten
call-by-reference benötigt man das nicht.
1
voidfoo(int&i)
2
{
3
i=5;
4
}
5
6
intmain()
7
{
8
intj;
9
10
foo(j);
11
}
Ein echter call-ba-reference zeichnet sich dadurch aus, dass in der
Argumentliste einfach nur die Kennung vorliegt, dass eine Referenz
erwartet wird. Alles andere ist syntaktisch identisch zum call-by-value
Fall
Karl Heinz schrieb:> Er braucht die Erkenntnis, dass Arrays nicht als ganzes zuweisbar sind.
Es ist mir schon klar, dass der gesamte Inhalt eines Arrays nicht so
kopiert werden kann. Aber es wird doch eh nur ein Zeiger auf das erste
Element von der Funktion zurückgegeben.
Wieso kann ich dann nicht einfach die Startadresse von testArray als
Pointer an array übergeben?
Das man C ausschliesslich Call-By-Value ausdrücken kann ist definitiv
falsch. Mit '*' (bzw. '&') werden Zeiger, also Referenzen deklariert.
Das aber ist nicht das Problem des TO.
Der springende Punkt ist ein bestimmter Satz im Kernighan&Ritchie in dem
es sinngemäß heisst, das der Name einer Array-Variablen synonym zu einem
Zeiger auf dieses Array ist. Anders ausgedrückt, wird jede Nennung des
Namens einer Array-Variablen, falls sie nicht durch andere Operatoren
noch modifiziert wird, durch einen Zeiger auf das erste Element dieses
Arrays ersetzt. Man muss das so auffassen, das an der Stelle des Namens
ein Literal erscheint, nämlich die Adresse des ersten Elementes.
Diese Aussage impliziert, dass die Nennung des Namens eines Arrays
nicht mit der Adresse einer Variablen gleich zu setzen ist, die einen
Zeiger enthält.
In der Verwendung des Namens gleicht dieser den Namen von
Zeigervariablen in einer bestimmten Hinsicht. Man kann dereferenzieren
bzw. den Index-Operator "[]" darauf verwenden.
In einer anderen Hinsicht aber entspricht er nicht den Namen von
Zeigervariablen. Er kann nicht verwendet werden um den Wert selbst zu
verwenden, da eben auch keine Variable existiert, die diesen Zeigerwert
enthält.
Etwas klarer wird das vielleicht, indem man in dem Code des TO die
Array-Namen, so wie es der Compiler macht durch die Addressen des ersten
Elementes ersetzt.
1
#include<stdio.h>
2
3
voidtest(unsignedchararray[]);
4
5
// Die Adresse des ersten Elementes von testArray sei einmal mit 0x1234 angenommen.
6
unsignedchartestArray[5]={3,4,5,6,7};
7
8
intmain()
9
{
10
// Die Adresse des ersten Elementes von mainArray sei einmal mit 0x5678 angenommen.
11
unsignedcharmainArray[5];
12
13
test(0x5678);
14
15
printf("%u",*((char*)(0x5678+0)));
16
17
return0;
18
}
19
20
voidtest(unsignedchararray[])
21
{
22
// Beim Aufruf wurde der Zeiger 0x5678 übergeben.
23
0x5678=0x1234;
24
}
Man sieht, dass man hier versucht ein Literal an ein Literal zuzuweisen.
Das geht natürlich nicht.
Hans schrieb:> Karl Heinz schrieb:>> Er braucht die Erkenntnis, dass Arrays nicht als ganzes zuweisbar sind.>> Es ist mir schon klar, dass der gesamte Inhalt eines Arrays nicht so> kopiert werden kann. Aber es wird doch eh nur ein Zeiger auf das erste> Element von der Funktion zurückgegeben.
Wo wird da irgendwas zurückgegeben?
> Wieso kann ich dann nicht einfach die Startadresse von testArray als> Pointer an array übergeben?
Kannst du doch.
Aber halt nur innerhalb der Funktion.
Du wunderst dich doch auch nicht, dass in
1
voidfoo(intj)
2
{
3
j=8;
4
}
5
6
intmain()
7
{
8
intk=5;
9
10
foo(k);
11
}
k nicht den Wert 8 kriegt.
Durch
1
voidtest(unsignedchar*array)
2
{
3
array=testArray;
4
}
hast du lediglich dem lokalen Pointer array innerhalb der Funktion einen
anderen Wert gegeben. Mehr ist nicht passiert.
Lös dich von der Vorstellung, dass es in C echtes Call-by-Reference
gäbe. Das gibt es in C nicht. Alles wird in C per Value übergeben. Das
inkludiert natürlich auch einen Pointer, der ebenfalls per Value
übergeben wird.
ImLichteArbeitender schrieb:> Das man C ausschliesslich Call-By-Value ausdrücken kann ist definitiv> falsch. Mit '*' (bzw. '&') werden Zeiger, also Referenzen deklariert.
Ein Zeiger ist keine Referenz.
Bitte verwirr denn TO nicht noch mehr.
Ein Problem ist auch, das mainArray ein Array ist.
Arrays kann man nach der Definiton weder in der Adresse noch in der
Größe ändern.
Wenn mainArray ein Pointer wäre, dann könnte man da was machen.
ImLichteArbeitender schrieb:> Das man C ausschliesslich Call-By-Value ausdrücken kann ist definitiv> falsch. Mit '*' (bzw. '&') werden Zeiger, also Referenzen deklariert.
Die Aussage war, daß in C kein cbr existiert, sondern nur cbv.
Natürlich kann man alles nachbauen, mehr oder weniger elegant: cbr,
Exceptions, Klassen und objektorientierte Programmierung, Continuations.
Daß C turing-vollständig ist, ist aber keine spannende Aussage.
Karl Heinz schrieb:> ImLichteArbeitender schrieb:>> Das man C ausschliesslich Call-By-Value ausdrücken kann ist definitiv>> falsch. Mit '*' (bzw. '&') werden Zeiger, also Referenzen deklariert.>> Ein Zeiger ist keine Referenz.
Selbstverständlich ist ein Zeiger eine Referenz. Was sonst? Synonym des
Wortes "Referenz" ist "Verweis" und was ein Zeiger funktional anderes
als ein Verweis auf eine Variable in C?
Michael schrieb:
> ImLichteArbeitender schrieb:>> Das man C ausschliesslich Call-By-Value ausdrücken kann ist definitiv>> falsch. Mit '*' (bzw. '&') werden Zeiger, also Referenzen deklariert.> Die Aussage war, daß in C kein cbr existiert, sondern nur cbv.
Genau. Und das habe ich als falsch bezeichnet.
Wenn ich den zeiger einer Variablen übergebe, dann ist das eine
Referenz. Also Call-By-Reference.
Ich mag mich ja irren, aber worin liegt mein Irrtum?
Sowohl sprachlich als auch von der Funktionsweise sehe ich nur
Bestätigungen meiner Auffassung.
ImLichteArbeitender schrieb:>> Die Aussage war, daß in C kein cbr existiert, sondern nur cbv.>> Genau. Und das habe ich als falsch bezeichnet.
Eben.
> Wenn ich den zeiger einer Variablen übergebe, dann ist das eine> Referenz. Also Call-By-Reference.
Nein, call by reference bezeichnet ein Sprachfeature, bei dem man nicht
"zu Fuß" irgendwelche Zeiger übergeben muß.
call by value, call by name, call by reference, call by value-result
haben klare Definitionen.
> Ich mag mich ja irren, aber worin liegt mein Irrtum?
Daß du das irgendwie als Angriff auf dich und deine Lieblingssprache
interpretierst. C hat kein call by reference. Ende. Aus.
Das Übergeben von Zeigern by value ist keine call by reference, sondern
etwas mti im wesentlichen demselben Effekt. Nur halt syntaktisch
unschön.
Michael schrieb:>> Ich mag mich ja irren, aber worin liegt mein Irrtum?>> Daß du das irgendwie als Angriff auf dich und deine Lieblingssprache> interpretierst. C hat kein call by reference. Ende. Aus.
Ich interpretiere das durchaus nicht als Angriff auf mich. Und eine
Lieblingssprache habe ich nicht. Nur weil ich anderer (und irriger
Meinung bin) und sie auch vertrete, heisst das ja nicht, dass ich mich
angegriffen fühle.
Das "Ende. Aus." aber hat mich tatsächlich beleidigt.
Jedenfalls Danke für die Information. Das kein zusätzliches syntaktische
Element vorkommen darf, sondern die Art und Weise implizit festgelegt
ist, habe ich zwar mal gewusst und reflektiert aber im Laufe der Jahre
ist das doch irgendwie verloren gegangen.
ImLichteArbeitender schrieb:> Das "Ende. Aus." aber hat mich tatsächlich beleidigt.
Was ist denn in dich gefahren?
Schalt den Rechner mal ein paar Stunden ab und beruhige dich erstmal.
Michael schrieb:> ImLichteArbeitender schrieb:>> Das "Ende. Aus." aber hat mich tatsächlich beleidigt.>> Was ist denn in dich gefahren?>> Schalt den Rechner mal ein paar Stunden ab und beruhige dich erstmal.
Ist denn etwas in mich gefahren? Was könnte das sein? Und ist Unruhe an
sich etwas, dass man ändern sollte? Wenn wir uns schon gegenseitig
Empfehlungen aussprechen, dann rate ich Dir zur Lektüre eines
Psychologie-Buches und eines über die Umgangssprache.