Zeiger:Kopie oder Zuweisung

Hallo,

Hier ist mein Problem:

int zeigerParameter(int *x)
{
int y;
y = *x; //Hier wird eine Kopie von x übergeben
}

int adressParam(int &x)
{
int y;
y = &x //Was passiert an der Stelle
//Ist es hier eine Zuweisung?
}

Gibt es eine Unterschiede zwischen die beide Funktione falls ja welche?

Danke.

Hossa :smile:

int zeigerParameter(int *x)
{
int y;
y = *x; //Hier wird eine Kopie von x übergeben
}

„x“ ist ein Zeiger auf ein int. Mit „*x“ dereferenzierst du den Zeiger und erhälst den Inhalt der Speicheradresse. Diesen Inhalt weist du nun der Variablen y zu.

int adressParam(int &x)
{
int y;
y = &x //Was passiert an der Stelle
//Ist es hier eine Zuweisung?
}

„x“ ist eine Referenz auf ein int. Du kannst diese Referenz „x“ genau so verwenden wie die Orignalvariable, die beim Aufruf der Funktion übergeben wird. Daher ist „&x“ die Adresse dieser Variablen, die dann an die int-Variable „y“ zugweiesen wird. Dabei wird der Compiler meckern, weil du der int-Variablen „y“ die Adresse einer int-Variablen also ein „int*“ zuweisen möchtest.

Gibt es eine Unterschiede zwischen die beide Funktione falls
ja welche?

Eine Referenz ist sozusagen eine Zeigervariable, die vom Compiler stets automatisch dereferenziert wird. Bei einem Zeiger musst du die Referenzierung explizit durch ein vorangestelltes „*“ bewirken.

Es gibt noch viele weitere kleine Unterschiede zwischen Zeigern und Referenzen. Ein weiterer wichtiger ist, dass Referenzen immer mit Variablen initialisiert werden müssen. Du kannst also z.B. nicht schreiben:

int x;
int &r;
r=x;

sondern es funktioniert nur:

int x;
int &r= x;

ich kann aber das schreiben:

int adressZeiger(int &x)
{
int y;
y = x;
}

Die Frage ist bei ist es eine Zuweisung oder wird eine kopie von x an y weiter gegeben?

Danke

ich kann aber das schreiben:

int adressZeiger(int &x)
{
int y;
y = x;
}

Richtig. Nur bei der Deklaration einer Referenz ist es zwingend notwendig, dass du schreibst, für welche Variable diese Referenz als Ersatz stehen soll. Hier hast du eine Referenz nur im Funktionskopf. Daher ist das x bereits eine Referenz aif eine andere Variable.

Die Frage ist bei ist es eine Zuweisung oder wird

Der Compiler schaut nach, was an der Speicheradresse der Variablen (hier der Referenz) x für ein Wert liegt. Nimmt diesen Wert als Kopie heraus und weist ihn der Variablen y zu. Danach existieren x und y unabahängig voneinander weiter. Eine Änderung an x oder y hat also keine Änderung der jeweils anderen Variablen zur Folge.

Schreibst du aber z.B. das hier:

int adressZeiger(int &x)
{
int &y= x;
}

So erzeugst du einen zweiten Namen, nämlich „y“, mit dem du die Variable (hier Referenz) x auch ansprechen kannst. Änderst du jetzt den Wert von x, wird automatisch der Wert von y entsprechend mit geändert, weil beide auf das selbe Ziel „zeigen“.

Mit anderen Worten, eine Referenz ist nur ein anderer Name für eine bestimmte Variable. Beide Namen identifizieren aber das selbe Ziel.

Viele Grüße

Ich habe noch ein folgendes Problem:

void function(int *x)
{
int *y;

y = x;

//Jetzt möchte ich sicherstellen daß y nicht auf NULL zeigt

if (y == NULL) // Wie sieht die Syntax hier aus?
std::cerr

Ich habe noch ein folgendes Problem:

void function(int *x)
{
int *y;

y = x;

//Jetzt möchte ich sicherstellen daß y nicht auf NULL zeigt

if (y == NULL) // Wie sieht die Syntax hier aus?
std::cerr

Hi allesamt,

NULL ist meistens als Makro wie folgt deklariert:
#define NULL ((void*)0)

In C: 7.17-3 "The macros (NULL,offsetof) are NULL which expands to an implementation defined null pointer constant ; and … Dto für NULL im C++ Standard (§C.2.2.3). Bei beiden wird der Wert nicht näher benannt. Insbesondere muss er nicht binär 0 sein.

In C++ ist aber zusätzlich auch definiert, dass „an integer constant expression with the value 0“ gecastet auf einen beliebigen Typ dann eine „null pointer constant of that type“ darstellt.

Eine wie auch immer geartete Konstante NULL muss in C++ mit normalen pointern wie auch mit pointer to members and pointer to member functions kompatibel sein, so dass sich in der Praxis der Wert „0“ (nicht (void*)0) für NULL ergibt.

Den feinen Unterschied sieht man z.B. hier

struct A {};
typedef int (A::\*p)(char\*);

int main()
{
 p xx = 0; // erlaubt !!!
 p yy = (void\*) 0; // nicht erlaubt !!
}

Wenn also NULL als „(void*)0“ in C++ definiert wäre, würde das zweite Assignment (p yy = NULL) fehlschlagen.

Die Notwendigkeit, hier NULL als 0 zu definieren, führt aber zu Mehrdeutigkeiten, wenn man Funktionen

void f(int a)
{
}

void f(char\* a)
{
}

vereinbart und dann f(NULL); aufruft.

Damit dieses „Chaos“ in Zukunft vermieden wird, gibt es ab dem neuen C++x09 Standard das nullptr keyword, das eine richtige null pointer constant ist.

Gruss
norsemanna

Hossa :smile:

Ja, da hast du schon Recht. Die Frage ist, worauf man mehr Wert legt, auf die Kompatibilität zu C oder auf die Einhaltung des C++ Standards. Deswegen habe ich geschrieben, dass NULL meistens als (void*)0 deklariert ist.

In der meines Compilers steht das so:

/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

Mit anderen Worten, im C++ Modus ist NULL eine „0“ und im C Modus ist NULL ein „(void*)0“…

Gut, dass das im neuen C++ Standard endlich gerade gezogen wird.

Danke für den Hinweis :smile:

Viele Grüße