Forum: Mikrocontroller und Digitale Elektronik Zeiger / Pointer in (µC)-C verstehen


von Michal (Gast)


Lesenswert?

Hallo Leute,

als Anfänger in der µC-Programmierung komme ich, mithilfe von diversen 
Tutorials, schön zügig voran, leider mit einer Ausnahme:

*Zeiger / Pointer in C.

Tut mir leid, egal an wievielen Orten ich es schon gelesen habe, ich 
checke es einfach nicht.

"Mit Zeiger oder Pointer wird eine spezielle Variable bezeichnet, die 
auf eine andere Variable oder Funktion verweist."

Soweit, so gut, das kann ich mir noch vorstellen.

Aber schlimmer sind dann die Code-Beispiele. Mir wird schon von den 
Klammern, Sternchen und anderen Symbolen schwindlig, und ich werde nicht 
schlau, warum es gerade so geschrieben wird.

Könnte mir jemand ein Beispiel von einem MINIMAL-CODE geben, wo jede 
Zeile ausführlich kommentiert ist, was und warum sie macht, und wo 
vielleicht noch eine einfache Zeichnung die Speicher-Zugriffe erklärt?

Es wird mich wesentlich weiter bringen.

An die hilfsbereiten vielen Dank voraus!

Grüße

Michal

von Maximilian M. (maxxel)


Lesenswert?

vielleicht hilft dir das kleine Video hier weiter:

http://cslibrary.stanford.edu/104/

von Gerd V. (gerald)


Lesenswert?

Ich hatte das gleiche Problem in den letzten Tagen, will auch in Zukunft 
mit C programmieren, konnte auch kaum was Brauchbares zu dem Thema 
finden.

Die Lösung ist ansich ganz einfach:
1. Buffer mit z.B. 40 Zeichen definieren, den dazugehörigen Zeiger 
nachfolgend definieren ...hier als *pBuffer bezeichnet ...alles in einer 
Zeile.

     unsigned char Buffer[40], *pBuffer;

Nächster Schritt:

     void Beispiel(void)
     {
     pBuffer = Buffer;
Nun zeigt der Zeiger auf die Anfangsadresse von Buffer, zwingend 
erforderlich ...aber ohne Stern!!!

    *pBuffer = 1;
Die Anfangsadresse von Buffer wurde nun mit dem Wert 1 geladen

    *pBuffer +1 = 2;
Adresse von Buffer +1, also um 1 erhöhen und eine 2 in den Buffer 
schreiben
    }

Wichtig ist, wenn man mit dem Zeiger arbeitet und Werte über den Zeiger 
in den Buffer schreiben bzw. lesen will das Sternchen vorneweg nicht 
vergessen!!!
Ich hoffe, es war auch ohne hochtrabende Verschachtelungen verständlich?

Viel Spass beim Programmieren

von Uhu U. (uhu)


Lesenswert?

Aus Prozessorsicht sind Pointervariable Variable, die die Adresse einer 
anderen Variablen enthalten.
1
  int Wert = 5;
2
  int *pW = NULL;    // Integerpointer definieren und mit NULL-Pointer init.
3
  
4
  pW = &Wert;        // Adresse von Wert an pW zuweisen
5
6
  printf("%d", *pW); // Inhalt der Variablen ausgeben, auf die pW zeigt

Das printf gibt 5 aus.

Für Arrays hat C eine besondere Regel parad: Der Arrayname ist eine 
Pointerkonstante. Deswegen muß man den Adressoperator & bei der 
Zuweisung der Adresse eines Strings weglassen.
1
  char str[] = "Hallo Welt";
2
  char *pS = NULL;    // Stringpointer definieren und mit NULL-Pointer init.
3
  
4
  pS = str;        // Adresse von str an pS zuweisen
5
6
  printf("%s", pS); // Inhalt der Variablen ausgeben, auf die pS zeigt

Hier gibt das printf den Text

   Hallo Welt

aus.

von GG (Gast)


Lesenswert?


von heinz (Gast)


Lesenswert?

Servus,
also Variabeln werden im Speicher abgelegt, jeder Speicherstelle hat 
eine eigen Adresse. Soweit so klar?

Ein Pointer ist nun eine spezielle Art einer Variable. In dieser 
Variable wird die Adresse einer anderen Variable (z.B. int, char, bool 
usw.) gespeichert.

Hier ein kleines Bsp:
1
#include <stdio.h>
2
3
int main(void)
4
  {
5
  int i;              //das ist eine Variable vom typ Integer (ganzzahl)
6
  int *pointer_auf_i; //das ist eine Variable vom Typ "pointer auf int 
7
 
8
  pointer_auf_i = &i; //der Adressoperator "&" liefert die Speicheradresse 
9
                      //von dr Variable "i" (da wo sie im speicher liegt)
10
11
  i = 10;             //die Variable "i" hat nun den wert 10
12
13
  printf("%p\n",pointer_auf_i);   //Die adresse von "i" wird ausgegeben
14
  printf("%i\n",*pointer_auf_i);  //Der Inhalt der Variable der an der in 
15
                                  //"pointer_auf_i" gespeicherten Adresse
16
                                  //wird ausgegeben
17
  }

von heinz (Gast)


Lesenswert?

und hier noch was zum testen, wie geht das wohl?
1
#include <stdio.h>
2
3
int main(void)
4
  {
5
  int i[10]= {1,2,3,4,5,6,7,8,9,10};
6
  int j;
7
  int *pointer_auf_i;
8
9
  pointer_auf_i = &i[0]; //übrigens liefert der name eines Array, also 
10
                         //ohne Klammern auh die adresse zurück
11
                         //also ist dies hier auch so möglich: 
12
                         // pointer_auf_i = i;
13
14
  j = *(i+2) * *(i+8);
15
  
16
  printf("%i * %i = %i\n", *(i+2),*(i+8), j);
17
18
  }

von Michal (Gast)


Lesenswert?

Hallo zusammen,

super, danke an Euch alle, einige Beispiele sind sehr einleuchtend.
Eine Frage fällt mir jetzt ein:

"printf("%p\n",pointer_auf_i);   //Die adresse von "i" wird ausgegeben"

Heisst es, dass ich hier echt die Adresse der Speicherzeile 
zurückkriege, so wie sie im Datenblatt durchnummeriert sind, z.B. $FC5?






#include <stdio.h>

int main(void)
  {
  int i;              //das ist eine Variable vom typ Integer (ganzzahl)
  int *pointer_auf_i; //das ist eine Variable vom Typ "pointer auf int

  pointer_auf_i = &i; //der Adressoperator "&" liefert die 
Speicheradresse
                      //von dr Variable "i" (da wo sie im speicher 
liegt)

  i = 10;             //die Variable "i" hat nun den wert 10

  printf("%p\n",pointer_auf_i);   //Die adresse von "i" wird ausgegeben
  printf("%i\n",*pointer_auf_i);  //Der Inhalt der Variable der an der 
in
                                  //"pointer_auf_i" gespeicherten 
Adresse
                                  //wird ausgegeben
  }

von Marvin M. (Gast)


Lesenswert?

"Heisst es, dass ich hier echt die Adresse der Speicherzeile
zurückkriege, so wie sie im Datenblatt durchnummeriert sind, z.B. $FC5?"

Jawoll.

von franz (Gast)


Lesenswert?

Meiner Meinung nach liegt eine Schwierigkeit darin, dass der "*" ein 
wenig seine Bedeutung ändert.

Beim Anlegen des Pointers

int *x;

liest man: lege einen Pointer mit dem Namen "x" an, der auf eine Integer 
Variable verweisst.

Bei der Benutzung später

int y;

y=*x;

liest man: weise der Variablen "y" den Wert der Speicherzelle zu, auf 
die der Pointer "x" zeigt.

von Michal (Gast)


Lesenswert?

Hallo,

ok, und wenn sich bei einem aufwendigen Programm der Speicherort einer 
Variablen ändert, weisst der Pointer das?

Grüße

Michal

von Stefan E. (sternst)


Lesenswert?

Und wo genau soll da jetzt die Änderung der Bedeutung sein?

"*x" ist einfach nur äquivalent zu "das worauf x zeigt".

int *x;
-> "das worauf x zeigt" hat den Typ int.

y=*x;
-> weise y den Wert von "das worauf x zeigt" zu.

von Stefan E. (sternst)


Lesenswert?

Michal schrieb:

> ok, und wenn sich bei einem aufwendigen Programm der Speicherort einer
> Variablen ändert, weisst der Pointer das?

Nein, aber Variablen springen auch nicht einfach im Speicher umher. ;-)

von Sven P. (Gast)


Lesenswert?

Gerd Vg schrieb:
>     *pBuffer +1 = 2;
Das vergessen wir dann auch bitte ganz schnell wieder und setzen ein 
Klammerpaar.

Ansonsten ist Zeigerrechnung keine Hexerei:
1
a[i] = *(a + i) = *(i + a) = i[a]
1
char *str = "abXde";
2
int idx = 2;
3
4
char c;
5
6
/* 
7
  Die folgenden Zeilen weisen der Variablen c ein 'X' zu
8
  und sind gültiges C:
9
*/
10
11
c = 'X';
12
c = str[2];
13
c = str[idx];
14
c = "abXde"[2];
15
c = "abXde"[idx];
16
c = 2[str];
17
c = idx[str];
18
c = idx["abXde"];
19
c = 2["abXde"];
20
c = *(str + 2);
21
c = *(2 + str);

von franz (Gast)


Lesenswert?

>Und wo genau soll da jetzt die Änderung der Bedeutung sein?
"*x" ist einfach nur äquivalent zu "das worauf x zeigt".
>int *x;
>-> "das worauf x zeigt" hat den Typ int.
>
>y=*x;
>-> weise y den Wert von "das worauf x zeigt" zu.

Meiner Meinung nach hat der "Stern" in der Deklaration und im Programm 
zwei verschiedene Bedeutungen:

int *x; // lege einen Pointer "x" an

Hier ist der Stern eine art erweiterte Typenbezeichnung, nämlich 
"Pointer". Der Pointer hat ja den Namen "x" und nicht "*x"

y=*x; // holle das worauf der Pointer "x" zeigt

Hier hat der Stern die Bedeutung "hole den Inhalt"

von Christian L. (lorio)


Lesenswert?

Sven P. schrieb:

> Ansonsten ist Zeigerrechnung keine Hexerei:
>
1
> a[i] = *(a + i) = *(i + a) = i[a]
2
>

Was diese "Gleichung" soll, verstehe ich auch nicht.
Ich würde sowieso behaupten, dass diese falsch ist, denn vor i muss noch 
eine Konstante (die Wortgröße).

von Stefan E. (sternst)


Lesenswert?

Christian L. schrieb:

> Ich würde sowieso behaupten, dass diese falsch ist, denn vor i muss noch
> eine Konstante (die Wortgröße).

Nein.
Schlage im nächstbesten C-Buch (oder online) "Zeigerarithmetik" nach.

von Karl H. (kbuchegg)


Lesenswert?

franz schrieb:
>>Und wo genau soll da jetzt die Änderung der Bedeutung sein?
> "*x" ist einfach nur äquivalent zu "das worauf x zeigt".
>>int *x;
>>-> "das worauf x zeigt" hat den Typ int.
>>
>>y=*x;
>>-> weise y den Wert von "das worauf x zeigt" zu.
>
> Meiner Meinung nach hat der "Stern" in der Deklaration und im Programm
> zwei verschiedene Bedeutungen:

Das kann man auf verschiedene Arten sehen.
Kernighan (der Mann der C entwickelt hat), hat die Definition von 
Pointer aus genau dem Grunde so gestaltet wie sie heute noch ist, weil 
die Definition wiederspiegelt.

   int *x;

bedeutet in den Augen des Sprachschöpfers:

  an der Stelle x im Speicher findet man einen int.

Die Definition von Pointern spiegelt also die Verwendung wieder. Das war 
die ganze ursprüngliche Idee.

von Christian L. (lorio)


Lesenswert?

Stefan Ernst schrieb:
> Christian L. schrieb:
>
>> Ich würde sowieso behaupten, dass diese falsch ist, denn vor i muss noch
>> eine Konstante (die Wortgröße).
>
> Nein.
> Schlage im nächstbesten C-Buch (oder online) "Zeigerarithmetik" nach.

Ok, ich muss mich verbessern, vor i kommt keine Konstante. Nach etwas 
Überlegung habe ich auch verstanden was hakus Gleichung bedeutet.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.