Supportnet / Forum / Anwendungen(Java,C++...)
Variablen vs. Zeiger
Frage
So, mal ne Anfängerfrage (ich beziehe mich auf C++, aber kann auch allgemein erklärt werden):
Welche Vorteile und Nachteile haben Zeiger gegenüber Variablen?
(sowohl theoretisch, als auch praktisch)
Hab ich irgendwie nie rausfinden können....
Antwort 1 von Nicole24
Referenzierungen und Dereferenzierungen
(oder "Zeiger und solche die es nicht mehr sein wollen")
Hier soll ein kurzer Überblick über die Funktionsweise von Zeigern in der Programmiersprache C gegeben werden.
Was ist eigentlich ein Zeiger?
Wenn man über eine Variable behauptet, sie sei ein Zeiger, dann stellt also ihr eigener Wert eine Adresse dar.
Anders, als wenn man einen Floatwert als Variable anlegt. Dann wird der Wert/Inhalt dieser Variable als Floatwert interpretiert.
Beispiel:
void main ()
{
float* x; // Variable x als Zeiger (x stellt Adresse dar)
float y; // Variable y Wert (y stellt float-Wert dar)
...
}
Von welchem Typ muss denn ein Zeiger sein?
Ein Zeiger ist immer von dem Typ, auf den er letztlich verweist. Wenn also ein Zeiger auf einen Zeiger ... auf einen Zeiger auf double angegeben ist, so ist der Datentyp des Zeigers double. Zusätzlich zum Datentypen werden noch die Anzahl Referenzierungen in Form der Sterne (*) vermerkt.
void main ()
{
double**** x; // Variable x als Zeiger (4 Referenzierungen)
...
}
Auch wenn es sich um Adresswerte handelt, ist der Datentyp von x nicht int!
Wie werden Inhaltsoperator (*) und Adressoperator (&) verwendet?
Folgendes vorweg: Bei Deklaration/Anlegen einer Variablen handelt es sich bei vorhandenen Sternen nicht um den Inhaltsoperator, sondern um die Anzahl der Referenzierungen!
Beispiel:
double* q; // Kein Inhaltsoperator, sondern Anzahl der Referenzierungen!
Den Inhaltsoperator * vor einen Zeiger (hier q) geschrieben, bewirkt eine Dereferenzierung. D.h. man kommt dem eigentlichen Datentyp (hier double) um eine Referenz näher. Da in obigem Beispiel nur eine Referenzierung (*) enthalten war, ist der damit ermittelte Datentyp double.
*q -> double
*q = 1.0;
Genau entgegengesetzt wirkt der Adressoperator &. Vor eine Variable geschrieben erhöht er die Anzahl der Referenzierungen um eins. Man entfernt sich also vom eigentlichen Datentypen. Auf obiges Beispiel angewandt, ergibt das:
&q // eine Referenzierung mehr, Typ des Gesamtausdrucks -> double**
Zur Verdeutlichung hier noch zwei Übersichten:
durch Anwendung des &-Operators kommen Referenzierungen hinzu
durch Anwendung des *-Operators werden Referenzierungen entfernt
Kleine "Eselsbrücke":
Jedes * vor einer Variablen zieht von der Deklaration dieser Variablen ein Stern ab. Ein & fügt eines zum Datentyp hinzu.
void main ()
{
char* s; // Datentyp von s ist char*
*s; // Datentyp des gesamten Ausdrucks ist char
...
}
(oder "Zeiger und solche die es nicht mehr sein wollen")
Hier soll ein kurzer Überblick über die Funktionsweise von Zeigern in der Programmiersprache C gegeben werden.
Was ist eigentlich ein Zeiger?
Wenn man über eine Variable behauptet, sie sei ein Zeiger, dann stellt also ihr eigener Wert eine Adresse dar.
Anders, als wenn man einen Floatwert als Variable anlegt. Dann wird der Wert/Inhalt dieser Variable als Floatwert interpretiert.
Beispiel:
void main ()
{
float* x; // Variable x als Zeiger (x stellt Adresse dar)
float y; // Variable y Wert (y stellt float-Wert dar)
...
}
Von welchem Typ muss denn ein Zeiger sein?
Ein Zeiger ist immer von dem Typ, auf den er letztlich verweist. Wenn also ein Zeiger auf einen Zeiger ... auf einen Zeiger auf double angegeben ist, so ist der Datentyp des Zeigers double. Zusätzlich zum Datentypen werden noch die Anzahl Referenzierungen in Form der Sterne (*) vermerkt.
void main ()
{
double**** x; // Variable x als Zeiger (4 Referenzierungen)
...
}
Auch wenn es sich um Adresswerte handelt, ist der Datentyp von x nicht int!
Wie werden Inhaltsoperator (*) und Adressoperator (&) verwendet?
Folgendes vorweg: Bei Deklaration/Anlegen einer Variablen handelt es sich bei vorhandenen Sternen nicht um den Inhaltsoperator, sondern um die Anzahl der Referenzierungen!
Beispiel:
double* q; // Kein Inhaltsoperator, sondern Anzahl der Referenzierungen!
Den Inhaltsoperator * vor einen Zeiger (hier q) geschrieben, bewirkt eine Dereferenzierung. D.h. man kommt dem eigentlichen Datentyp (hier double) um eine Referenz näher. Da in obigem Beispiel nur eine Referenzierung (*) enthalten war, ist der damit ermittelte Datentyp double.
*q -> double
*q = 1.0;
Genau entgegengesetzt wirkt der Adressoperator &. Vor eine Variable geschrieben erhöht er die Anzahl der Referenzierungen um eins. Man entfernt sich also vom eigentlichen Datentypen. Auf obiges Beispiel angewandt, ergibt das:
&q // eine Referenzierung mehr, Typ des Gesamtausdrucks -> double**
Zur Verdeutlichung hier noch zwei Übersichten:
durch Anwendung des &-Operators kommen Referenzierungen hinzu
durch Anwendung des *-Operators werden Referenzierungen entfernt
Kleine "Eselsbrücke":
Jedes * vor einer Variablen zieht von der Deklaration dieser Variablen ein Stern ab. Ein & fügt eines zum Datentyp hinzu.
void main ()
{
char* s; // Datentyp von s ist char*
*s; // Datentyp des gesamten Ausdrucks ist char
...
}
Antwort 2 von Claas
Hmm, danke erstmal....aber warum sollte man Zeiger denn benutzen???
Antwort 3 von FrankieH
Zig Gründe:
Auf einen Wert mit verschiedenen Variablennamen zugreifen,
Übergabe an Funktionen (ein Zeiger belegt nur 4 Byte auf dem Stack, ein double dagegen 8)
Wenn in der Funktion der Wert verändert werden soll, dann per Zeiger übergeben.
Übersichtlichere Schreibweise, wenn man in Stukturen auf Unterstrukturen zugreifen möchte und nich immer den langen Namen schreiben möchte,
usw.
Auf einen Wert mit verschiedenen Variablennamen zugreifen,
Übergabe an Funktionen (ein Zeiger belegt nur 4 Byte auf dem Stack, ein double dagegen 8)
Wenn in der Funktion der Wert verändert werden soll, dann per Zeiger übergeben.
Übersichtlichere Schreibweise, wenn man in Stukturen auf Unterstrukturen zugreifen möchte und nich immer den langen Namen schreiben möchte,
usw.
Antwort 4 von lukas
moin
zeiger machen auch erst einen datenaustausch zwischen Objekten möglich (es geht auch ohne, is aber mega aufwendig)
ausserdem stell dir mal vor du übergibts ein Array, das so ein paar mb groß ist, an eine Funktion ohne Zeiger, das wäre nich so toll, weil dann eine kopie des Arrays "übergeben" wird.
In C/C++ kann man Arrays nicht ohne Zeiger übergeben aber zb. in Pascal müsste das gehen.
zeiger machen auch erst einen datenaustausch zwischen Objekten möglich (es geht auch ohne, is aber mega aufwendig)
ausserdem stell dir mal vor du übergibts ein Array, das so ein paar mb groß ist, an eine Funktion ohne Zeiger, das wäre nich so toll, weil dann eine kopie des Arrays "übergeben" wird.
In C/C++ kann man Arrays nicht ohne Zeiger übergeben aber zb. in Pascal müsste das gehen.
Antwort 5 von TheRealWhistler
Nicole24 wrote:
void main ()
{
float* x; // Variable x als Zeiger (x stellt Adresse dar)
float y; // Variable y Wert (y stellt float-Wert dar)
...
}
=======
Hi,
in dem oben genannten Beispiel sollte man beachten, dass man x, nach seiner Deklaration nicht so ohne weiteres zum "speichern" eines Wertes (vom Typ float ) verwenden kann, da der Zeiger x Anfangs auf keinen Gültigen Speicher zeigt.
z.B:
float *x;
float y;
*x = 1.0; // führt zu einem GP-Fault (General Protection Fault)
aber:
float *x;
float y;
x = &y;
x = 1.0; // gültig, da x auf die Speicherstelle von y zeigt
if( y == 1.0) ...; // Bedingung ist immer Wahr
ciao
Andreas
void main ()
{
float* x; // Variable x als Zeiger (x stellt Adresse dar)
float y; // Variable y Wert (y stellt float-Wert dar)
...
}
=======
Hi,
in dem oben genannten Beispiel sollte man beachten, dass man x, nach seiner Deklaration nicht so ohne weiteres zum "speichern" eines Wertes (vom Typ float ) verwenden kann, da der Zeiger x Anfangs auf keinen Gültigen Speicher zeigt.
z.B:
float *x;
float y;
*x = 1.0; // führt zu einem GP-Fault (General Protection Fault)
aber:
float *x;
float y;
x = &y;
x = 1.0; // gültig, da x auf die Speicherstelle von y zeigt
if( y == 1.0) ...; // Bedingung ist immer Wahr
ciao
Andreas
Antwort 6 von TheRealWhistler
Sorry
x = 1.0; // gültig, da x auf die Speicherstelle von y zeigt
sollte
*x = 1.0; // gültig, da x auf die Speicherstelle von y zeigt
(kleiner Schusselfehler von mir)
x = 1.0; // gültig, da x auf die Speicherstelle von y zeigt
sollte
*x = 1.0; // gültig, da x auf die Speicherstelle von y zeigt
(kleiner Schusselfehler von mir)

