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:
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.
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.
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.