Funktionsschnittstelle Array oder Zeiger auf Array?
-
void test(int array[]){ // int array[] = int *array printf("%d %d %d",&array,array,array[1]); } int main() { int array[2]={1,2}; printf("%d %d %d\n",&array,array,array[1]); test(array); }
Hallo, habe folgende Frage:
An einer Funktionsschnittstelle, wie oben:void test(int *array) oder halt void test(int array[])...
wird hier eigentlich nur ein Zeiger auf das Array erstellt,weil wenn ich die Funtkion aufrufe, übergebe ich ja die Adresse vom Array an den formalen Parameter.
Dieser speichert quasi die Basisadresse dann vom Array;wenn ich aber int array[2] schreibe, wird doch nicht ein ganzes Array erstellt oder?
Arrays werden doch immer als Referenz übergeben(call by reference)?
*d.h. in der Funktion wird nur ein Zeiger erstellt, der auf das Array zeigt,
egal ob ich schreibe array oder array[] ??zum Zweiten:
hab bei der Übergabe von structs noch eine Frage:also z.b.
typedef struct stk { int *elems[MAX];int top;}stack; int isEmpty(stack s){ return (s.top==0);} int* Pop(stack *s){ if(isEmpty(*s)) return 0; s->top--; return s->elems[s->top]; } main funktion... stack s; Pop(&s);
Hier wird doch bei Pop(&s) zuerst einmal die Adresse vom Struct übergegen an einen Zeiger. call by reference.
Nun wird bei isEmpty(*s) die Variable selbst übergeben(call by value)?
Und in der isEmpty Funktion wird eine Kopie der Variable geprüft,oder?
Würde ich da was ändern, hätte das keine Auswirkung?Wäre super nett, wenn sich das mal jemand angucken könnte?
-
In C gibt es keine Referenzen. Es ist immer call by value.
Arrays werden immer als Zeiger auf ihr erstes Element übergeben, daher musst du immer die Anzahl der Elemente im Array mit übergeben.
Hier eine Beispielfunktion, die alle Elemente im Array summiert:
int myArrFunc(int *arr, size_t size) { int sum = 0; for (; size != 0; --size) sum += arr[size - 1]; return sum; }
Alternativ kannst du statt "int *arr" auch "int arr[]" schreiben, um zu verdeutlichen, dass du hier ein Array erwartest. Syntaktisch ist beides identisch.
-
Janjan schrieb:
In C gibt es keine Referenzen. Es ist immer call by value.
Man könnte jetzt darüber streiten, ob man die Zeiger-Übergabe per Kopie wirklich immer als call by value bezeichnen will, oder ob man das nicht doch call by reference nennt, weil schließlich der Zeiger die Referenz darstellt und man damit das typische call by reference Verhalten erreicht (abgesehen natürlich von den weiterführenden Dingen, die man mit den Zeigern so anstellen kann), wie man es aus anderen Sprachen kennt. :p
-
_matze schrieb:
Janjan schrieb:
In C gibt es keine Referenzen. Es ist immer call by value.
Man könnte jetzt darüber streiten, ob man die Zeiger-Übergabe per Kopie wirklich immer als call by value bezeichnen will, oder ob man das nicht doch call by reference nennt, weil schließlich der Zeiger die Referenz darstellt und man damit das typische call by reference Verhalten erreicht (abgesehen natürlich von den weiterführenden Dingen, die man mit den Zeigern so anstellen kann), wie man es aus anderen Sprachen kennt. :p
Kann man nicht. Es wird eine Kopie des Zeigerwertes übergeben. Also wieder call by value. Ein Zeiger ist einfach ein Zeiger, keine Referenz eines Objektes. Ein Zeiger kann schließlich auf beliebigen Mist zeigen.
-
mit call-by-reference meinte ich auch das Verhalten...
wir haben das in der Vorlesung so gelernt, dass man mit den Zeigern das call-by-reference von C++ nachahmen kann..."int *arr" auch "int arr[]"
also d.h.
würde ich das in der main-Funktion schreiben,
dann würde ich mit
int *arr einen Zeiger erstellen und mit
int arr[]={...} ein Array?aber an der Funktionsschnittstelle ist das dann dasselbe?
wenn ich aber statt int arr[] schreibe int arr[10], macht das doch eigentlich
kein Unterschied oder, es bleibt ein Zeiger quasi auf das erste Array-Element oder nicht?
-
smileC89 schrieb:
mit call-by-reference meinte ich auch das Verhalten...
wir haben das in der Vorlesung so gelernt, dass man mit den Zeigern das call-by-reference von C++ nachahmen kann...Nachahmen ja. Aber es ist und bleibt call by value.
[quote="smileC89"]
"int *arr" auch "int arr[]"also d.h.
würde ich das in der main-Funktion schreiben,
dann würde ich mit
int *arr einen Zeiger erstellen und mit
int arr[]={...} ein Array?aber an der Funktionsschnittstelle ist das dann dasselbe?[/qzote]
Ja.smileC89 schrieb:
wenn ich aber statt int arr[] schreibe int arr[10], macht das doch eigentlich
kein Unterschied oder, es bleibt ein Zeiger quasi auf das erste Array-Element oder nicht?Du kannst Funktionen keine Arrays übergeben. Nur Zeiger.
Schreibst du "char a[2]" so ist der Typ trotzdem ein "char*" und nicht "char[2]".
-
Janjan schrieb:
Kann man nicht. Es wird eine Kopie des Zeigerwertes übergeben. Also wieder call by value. Ein Zeiger ist einfach ein Zeiger, keine Referenz eines Objektes. Ein Zeiger kann schließlich auf beliebigen Mist zeigen.
Aber der Wert des Zeigers ist eine Referenz.
-
mngbd schrieb:
Janjan schrieb:
Kann man nicht. Es wird eine Kopie des Zeigerwertes übergeben. Also wieder call by value. Ein Zeiger ist einfach ein Zeiger, keine Referenz eines Objektes. Ein Zeiger kann schließlich auf beliebigen Mist zeigen.
Aber der Wert des Zeigers ist eine Referenz.
Nein, ist es nicht. Ein Zeiger ist ein Zeiger. Es _kann_ auf eine Variable zeigen, muss es aber nicht.
-
Janjan schrieb:
Schreibst du "char a[2]" so ist der Typ trotzdem ein "char*" und nicht "char[2]".
naja das stimmt doch nicht ganz oder
wär es ein char* könnte man auch
char a[2]; char *b="asd"; a = b;
iwie muß da schon ein unterschied sein.
lg lolo
-
Janjan schrieb:
Kann man nicht. Es wird eine Kopie des Zeigerwertes übergeben. Also wieder call by value. Ein Zeiger ist einfach ein Zeiger, keine Referenz eines Objektes. Ein Zeiger kann schließlich auf beliebigen Mist zeigen.
syntaktisch gesehen hast du Recht, semantisch gesehen verwendet man Zeiger, um call-by-reference zu erlauben. Und Zeiger kann man sehr wohl als Referenzen zu Objekten sehen, jedoch nicht als C++-Referenzen, den Fehler scheinst du zu machen.
GTK+ ist in C geschrieben, wenn ich sowas mache:
GtkWindow *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
dann ist
win
syntaktisch gesehen nur ein Zeiger, aber semantisch gesehen eine Referenz zu einem GtkWidget Objekt von Typ GTK_WINDOW und genauso wird sie inetrn (in GTK+) und extern behandelt.
-
ah ok... danke
wollte nur noch zum Abschluss kurz fragen,
wie das bei meiner zweiten Frage ist:Pop(&s);
hier übergebe ich die Adresse von der Variablen s ...int* Pop(stack *s){
// hier erstelle ich dann einen Zeiger auf die Variable s...if(isEmpty(*s)) return 0;
*// hier übergebe ich das Objekt selbst, bzw. die Variable, auf die s zeigt,oder?s->top--;
return s->elems[s->top];
}int isEmpty(stack s){
// hier wurde also eine Kopie angelegt?!Änderungen an s würden keine Änderungen an dem Ursprungs-S bewirken,oder? zum testen, ob s.top==0 reicht es, allerdings
wäre s jetzt ein größerer Speicherblock, wäre das mit dem Zeiger ressourcenschonender? oder?return (s.top==0);}
-
noobLolo schrieb:
Janjan schrieb:
Schreibst du "char a[2]" so ist der Typ trotzdem ein "char*" und nicht "char[2]".
naja das stimmt doch nicht ganz oder
wär es ein char* könnte man auch
char a[2]; char *b="asd"; a = b;
iwie muß da schon ein unterschied sein.
Dies bezog sich ausschließlich auf Funktionsparameter. Du kannst es gerne selbst ausprobieren:
void Foo(char a[99]) { printf("%d\n", sizeof(a)); }
Die Ausgabe wird 4 sein (32 bit System), da es sich um einen Zeiger handelt, und nicht um ein Array mit 99 Elementen.
supertux schrieb:
Janjan schrieb:
Kann man nicht. Es wird eine Kopie des Zeigerwertes übergeben. Also wieder call by value. Ein Zeiger ist einfach ein Zeiger, keine Referenz eines Objektes. Ein Zeiger kann schließlich auf beliebigen Mist zeigen.
syntaktisch gesehen hast du Recht, semantisch gesehen verwendet man Zeiger, um call-by-reference zu erlauben. Und Zeiger kann man sehr wohl als Referenzen zu Objekten sehen, jedoch nicht als C++-Referenzen, den Fehler scheinst du zu machen.
GTK+ ist in C geschrieben, wenn ich sowas mache:
GtkWindow *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
dann ist
win
syntaktisch gesehen nur ein Zeiger, aber semantisch gesehen eine Referenz zu einem GtkWidget Objekt von Typ GTK_WINDOW und genauso wird sie inetrn (in GTK+) und extern behandelt.Ich habe nie behauptet, dass es semantisch so nicht ist. Nur von der technischen Seite ist es immer call by value. C unterstützt keine Referenzen, deswegen nutzt man stattdessen Zeiger auf Variablen.
smileC89 schrieb:
int isEmpty(stack s){
// hier wurde also eine Kopie angelegt?!Änderungen an s würden keine Änderungen an dem Ursprungs-S bewirken,oder? zum testen, ob s.top==0 reicht es, allerdings
wäre s jetzt ein größerer Speicherblock, wäre das mit dem Zeiger ressourcenschonender? oder?Richtig.
-
Ok danke
so jetzt hab ichs
-
Janjan schrieb:
Ein Zeiger ist ein Zeiger. Es _kann_ auf eine Variable zeigen, muss es aber nicht.
Naja, tut er aber normalerweise. Genauso könntest du behaupten, dass in einem String keine Zeichen sind, weil es den leeren String gibt.
Wenn ein Zeiger keine Referenz auf irgendwas ist, was ist er dann?