Pointer und Reference
-
Tom83 schrieb:
Hallo,
ich hab grad keinen Compiler da.
Kann ich ein komplettes Array mit Objekten als Argument an eine Methode in einer anderen Klasse übegeben, indem ich die Klammern weglasse?
Viele Grüße
Aber nur, wenn du den Index auch weglässt.
In der Funktion würde dann natürlich ein Array erwartet. Weil das Array aber viele Elemente aufweisen kann, wird keine tiefe, sondern eine flache Kopie erstellt, oder genauer: Die Funktion erhält lediglich einen Verweis auf das Array.
Jetzt wird es vor allem für Anfänger kompliziert: wenn du ein Array an eine Funktion gibst:
//Änderungen hier am Array betreffen auch das Original ... void MyProc(char MyArray[]){...} int main() { char MyArray[10]; MyProc(MyArray); return 0; }, kannst du im Funktionskopf das Array auch als Zeiger angeben - denn intern wird das Ganze eh in eine Adresse umgewandelt.
//Funktioniert auch so void MyProc(char*MyArray){...} int main() { char MyArray[10]; MyProc(MyArray); return 0; }Das heißt nicht, dass
MyArrayzu einem Zeiger wird - ein Array an sich ist fix, man kann ihm nichts zuweisen (wohl aber den Elementen)://Geht nicht! MyArray=OtherArray; //Geht doch! MyArray[1]=OtherArray[2];Einem Zeiger kann man was zuweisen:
//Geht! MyPointer=MyArray; //Geht auch (wenn MyPointer was zugewiesen wurde)! MyPointer[1]=MyArray[2];Arrays und Zeiger sind nicht ein und dasselbe, auch wenn der Zugriff erschreckend ähnlich erfolgt.
Im Grunde ist es egal - ich weiß nicht, wie der Compiler reagiert, wenn du versuchst, einem Array in einer Funktion, in der es als Zeiger vertreten ist, etwas zuzuweisen, aber er sollte es abstrafen. Aber für die bessere Lesbarkeit solltest du immer zu
[], wenn du Speicher auf dem Stack, und zu*, wenn du Speicher auf dem Heap erwartest, verwenden.
-
Das wichtigste dazu wurde aber noch nicht gesagt. Übergibt man ein Array an eine Funktion
void foo(char* arr);oder
void bar(char arr[]);, dann geht die Information über die Länge des Arrays verloren! http://ideone.com/NBqtR
2 Möglichkeiten gibt es, um das Problem zu lösen:
1.)Eine Referenz auf das Array übergeben. Dies ist die unleserliche, komplizierte Variante: http://ideone.com/elCPx
2.)Einen Container deiner Wahl nehmen, der Ersatz für ein Array heißt std::tr1::array (bzw std::array, wenn du unter C++0x bist). Findet sich im Header <array>.
Verwendung: http://ideone.com/ArtD2Wenn du einen dynamischen Container brauchst, dann ein std::vector.
Variante 2 ist eigentlich immer zu bevorzugen!
-
Hallo!
Ich habe noch eine Frage:
Auf der ersten Seite stand ja folgendes (manni) hat das geschrieben:
Tom83 schrieb:
Wie kann man denn rausfinden ob schon ein Zeiger angelegt wurde?
Das kann man nicht herausfinden. Du kannst nur testen, ob ein Pointer kein 0-Zeiger ist. Dazu musst du natürlich dein Array erst mal mit 0 initialisieren:
C/C++ Code:
Saeugetier *s1[10] = {};
C/C++ Code:
Saeugetier *s1[10] = {};
C/C++ Code:
Saeugetier *s1[10] = {};Anschließend kannst du dann prüfen:
C/C++ Code:
bool pruef (Saeugetier s) {
cout << "speicherbereich verweist auf:" << (void)s;if (s == 0) {
C/C++ Code:
bool pruef (Saeugetier s) {
cout << "speicherbereich verweist auf:" << (void)s;if (s == 0) {
C/C++ Code:
bool pruef (Saeugetier s) {
cout << "speicherbereich verweist auf:" << (void)s;if (s == 0) {
Die Funktion wird jetzt natürlich anders aufgerufen:
C/C++ Code:
flag = test->pruef(s1[i]);
C/C++ Code:
flag = test->pruef(s1[i]);
C/C++ Code:
flag = test->pruef(s1[i]);Die Methode
bool pruef (Saeugetier *s)funktioniert auch so:
bool pruef (Saeugetier s[])Warum ist dass denn so? Meine Vermutung: Das Array ist ja an sich eh schon ein Zeiger?
Wenn ich bool pruef (Saeugetier *s[]) eingebe, dann kommt die Fehlermeldung "canot convert from int* to int**) (Das hat meine Vermutung erzeugt, dass hier das Array von sich aus standardmäßig als Zeiger dient und deshalb nicht extra als Zeiger deklariert werden muss?Viele Grüße
Viele Grüße
-
Ein Array ist kein Zeiger. Allerdings wird der Array-Name in den meisten Situationen implizit in einen Zeiger auf das erste Array-Element umgewandelt.
(und bei Funktionsparametern sind die Angabenint *aundint a[]tatsächlich äquivalent, allerdings nur in der äußersten Dimension)
-
Dankeschön!
Was passiert denn eigentlich bei
cout << "der Speicherbereich verweist auf" << (void*) sdie folgende Zeile bewirkt das gleiche:
cout << "der Speicherbereich verweist auf" << sIch hab zwar was von void - Zeigern gelesen, aber noch nicht so recht verstanden.
bedeutet (void*) s hier evtl. dass mit dem Objekt s selbst gearbeitet wird, also eine andere Schreibweise für "s"?Gruß
-
(void*)s ist ein Cast im C-Stil, also eine Typ-Umwandlung. Das heißt, daß du den struct-Zeiger explizit in einen void-Zeiger (=Zeiger auf unstrukturierten Speicher) umwandelst. Bei der Variante
cout << s;hast du ebenfalls eine Typumwandlung, allerdings eine implizite.
(bei der Struktur macht das keinen Unterschied, aber wenn du stattdessen einchar *sverwendest, unterscheiden sich die Ausgaben)
-
Hi @ all,
ich habe den Thread durchgelesen und noch eine Frage zu dem ganzen Thema.
Ich habe folgende Zeilen geschrieben, und bitte euch diese zu kontrollieren ob das alles stimmt (vor allem die Kommentare)
#include <cstdlib> #include <iostream> using namespace std; void kopie (int z) { cout << "FUNKTION kopie(int z) " <<endl; //z hat eine eigene Adresse und ist nicht mit a verbunden cout << "Die Adresse von z:" << &z << endl; cout << "Der WErt von z: " << z << endl << endl<< endl << endl; //eine Zuweisung bringt hier nichts, a bleibt unverändert! z = 99; } //Übergabe als Referenz void referenz (int &x) { cout << "FUNKTION referenz (int &x) " << endl; //die Adresse von y entspricht der von a, da mit einem //Alias gearbeitet wird???? cout << "Die Adresse von x: " << &x << " entspricht der von a, da ein Alias von a" << endl; cout << "Der Wert von x: " << x << endl << endl <<endl << endl; //Änderungen würden sich hier direkt auf a auswirken! } void pointer (int &y) { cout << "FUNKTION pointer (int &y)" << endl; //y hat eine eigene Adresse, da ein dereferenzierter Zeiger übergeben wurde cout << "Die Adresse von y (&y):" << &y <<endl; cout << "Der Wert von y (y) :" << y <<endl << endl<< endl << endl; //Änderungen würden sich hier direkt auf b auswirken! } int main(int argc, char *argv[]) { int a = 5; int b = 8; int *c = &b; cout << "Die Adresse von a: " << &a << endl; cout << "Der Wert von a: " << a <<endl << endl; //hier wird die Zahl a übergeben (kein Pointer oder Referenz)??? referenz(a); //hier wird die Zahl a übergeben (kein Point oder Referenz)?? kopie(a); cout << "Die Adresse von b (&b): " << &b << endl; cout << "Der Wert von b (b): " << b << endl; cout << "Die Adresse von c (&c): " << &c << endl; cout << "Der Wert von c (c): " << c << " (also die Adresse von b)" << endl; //der Zeiger *c wird nun dereferenziert cout << "Der Wert - verweis c (*c): " << *c << " (also der Wert von b)" << endl << endl; pointer(*c); /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// //NEUER Quellcodebereich/////////////////////////////////////////////////////////////////// //Beispiel REFERENZEN int aa = 6; //Was weiße ich hier genau zu?? ?? //das heißt ja ungegfähr "die Adresse von bb entsprich aa (aber "aa" ist ja der Wert, oder?? int &bb = aa; //BEISPIEL ZEIGER int cc = 9; //Dem Zeiger *dd wird die Adresse von cc zugewiesen int *dd = &cc; int ee = 11; cout << "bb" << bb << endl; //die Referenz bb erhält den Wert von ee ... bb = ee; //... da bb direkt auf aa verweist, nimmt aa den Wert von ee an. cout << "aa" << aa << endl << endl << endl; //*dd liefert den dereferenzierten Wert cout << "cc" << cc << endl; cout << "*dd" << *dd << endl; //NUN VERWEIST dd AUF DIE ADRESSE VON "ee" dd = ⅇ cout << "cc erneut" << cc <<endl; cout << "*dd erneut" << *dd << endl; system("PAUSE"); return EXIT_SUCCESS; }was ich noch nicht so ganz verstehe:
Was wird bei "void referenz (int &x)" bzw. "void pointer (int &x)" übergeben? Es handelt sich doch in beiden Fällen um Objekte bzw. int - Werte??
Tschau
-
http://ideone.com/wRmYi
Wird es dadurch etwas klarer?
Übrigens schreibt man im Normalfall int& n, nicht int &n, selbiges mit Zeigern.
-
Mario2hoch6 schrieb:
Was wird bei "void referenz (int &x)" bzw. "void pointer (int &x)" übergeben? Es handelt sich doch in beiden Fällen um Objekte bzw. int - Werte??
Genau genommen übergibst du an beide Funktionen eine Referenz. Übergabe per Zeiger sieht ein wenig anders aus:
void pointer (int *y) { cout << "FUNKTION pointer (int *y)" << endl; //y hat eine eigene Adresse, da ein Zeiger übergeben wurde cout << "Die Adresse von y (&y):" << &y <<endl; //y enthält die Adresse einer übergebenen Variablen cout << "Der Wert von y (y) :" << y <<endl< //y ist ein Pointer und zeigt auf eine Variable cout << "Der Wert hinter y (*y):" << *y << endl<< endl << endl; //Änderungen an *y würden sich hier direkt auf b auswirken! } //Aufruf per: int a; zeiger(&a);
-
Hi,
warum übergibst du hier
pointer(&b)(also die Adresse der Variabeln) ich hätte das so gemacht:
int b = 8; int* c = &b; pointer(c);c enthält ja auch die Adresse der Variablen b. Allerdings warum hast du hier keinen Zeiger mit "int* c" angelegt?
Viele Grüße
-
Tom83 schrieb:
Hi,
warum übergibst du hier
pointer(&b)(also die Adresse der Variabeln) ich hätte das so gemacht:
int b = 8; int* c = &b; pointer(c);c enthält ja auch die Adresse der Variablen b. Allerdings warum hast du hier keinen Zeiger mit "int* c" angelegt?
Viele Grüße
Weil es nicht notwendig ist. Der Parameter (d.h. die Adresse von b) wird sowieso in den Stack-Bereich der Funktion kopiert, da ist es nicht notwendig, noch eine eigene Variable dafür anzulegen.
-
Hi,
wie schauts dann aus, wenn ich so ein Konstrukt habe:
//call by VALUE void test3 (int q) { q = 77777; cout << " BEI q steht folgendes " << q << endl; } int s =99; int *r = &s; test3(*r); cout << "Der Wert von *r :" << *r << endl; cout << "Der wert von s: " << s << endl;Nennt man das dass call by Value, oder hat das einen anderen Namen, weil ich einen derefferenzierten Zeiger übergebe?
Viele Grüße
-
Das ist call by value, weil die Funktion einen Wert übergeben bekommt. Woher dieser Wert stammt, ist für den Aufruftyp unerheblich.
Rein technisch gesehen ist auch die Zeiger-Variante "call by value" (allerdings mit einem "int*" Wert), semantisch wurde sie in C verwendet, um "call by reference" Semantik nachzubilden.
-
Hi!
Danke!
Ich hab mich jetzt mal an das Thema Zeiger auf Zeiger rangewagt:
int s =99; int *r = &s; int **zeigeraufzeiger; int ***zeigeraufzeigeraufzeiger; zeigeraufzeiger = &r; zeigeraufzeigeraufzeiger = &zeigeraufzeiger; cout << "Adresse von s (&s) " << &s <<endl; cout << "Wert des Zeigers r (r) " << r << endl; cout << "Adresse des Zeiger r (&r) " << &r << endl; cout << "Wert des zeigeraufzeiger (z...) " << zeigeraufzeiger << endl; cout << "Adresse des zeigersaufzeiger (&z...) " << &zeigeraufzeiger << endl; cout << "Wert des zeigeraufzeigeraufzeiger (z...) " << zeigeraufzeigeraufzeiger << endl; cout << "Adresse des zeigeraufzeigeraufzeiger (&z...) " << &zeigeraufzeigeraufzeiger << endl <<endl << endl; cout << "Wert von s " << s << endl; cout << "Wert des Zeigers r (*r) " << *r << endl; cout << "zeigeraufzeiger (z...) " << zeigeraufzeiger << endl; cout << "Wert des Zeigers zeigeraufzeiger (*zei...) (wert von r) " <<*zeigeraufzeiger << endl; cout << "Wert des Zeigers zeigeraufzeiger (**zei...) (wert von s) " << **zeigeraufzeiger << endl <<endl; cout << "zeigeraufzeiger (z...) " << zeigeraufzeigeraufzeiger << endl; cout << "Wert Zeiger zeigeraufzeigeraufzeiger (*z...)(wert von zeigeraufzeiger) " << *zeigeraufzeigeraufzeiger << endl; cout << "Wert des Zeigers zeigeraufzeigeraufzeiger (**z...) (Wert von r) " << **zeigeraufzeigeraufzeiger << endl; cout << "Wert des Zeigers zeigeraufzeigeraufzeiger (***z..) (Wert von s) " << ***zeigeraufzeigeraufzeiger << endl;Stimmen meine Angaben so?
Viele Grüße
-
Nicht ganz.
Zeile 18: Ziel des Zeigers
Zeile 22: Ziel des Zeigers
Zeile 23: Ziel des Zieles des ZeigersZeile 27: Ziel des Zeigers
Zeile 28: Ziel des Zieles des Zeigers
Zeile 29: Ziel des Zieles des Zieles des Zeigers