mikrocontroller.net

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


Autor: Michal (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Maximilian Matthe (maxxel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielleicht hilft dir das kleine Video hier weiter:

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

Autor: Gerd Vg (gerald)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aus Prozessorsicht sind Pointervariable Variable, die die Adresse einer 
anderen Variablen enthalten.
  int Wert = 5;
  int *pW = NULL;    // Integerpointer definieren und mit NULL-Pointer init.
  
  pW = &Wert;        // Adresse von Wert an pW zuweisen

  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.
  char str[] = "Hallo Welt";
  char *pS = NULL;    // Stringpointer definieren und mit NULL-Pointer init.
  
  pS = str;        // Adresse von str an pS zuweisen

  printf("%s", pS); // Inhalt der Variablen ausgeben, auf die pS zeigt


Hier gibt das printf den Text

   Hallo Welt

aus.

Autor: GG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Servus,

hier eine gute Anleitung:

http://www4.informatik.uni-erlangen.de/Lehre/SS06/...

Gruß GG

Autor: heinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#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
  }

Autor: heinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und hier noch was zum testen, wie geht das wohl?
#include <stdio.h>

int main(void)
  {
  int i[10]= {1,2,3,4,5,6,7,8,9,10};
  int j;
  int *pointer_auf_i;

  pointer_auf_i = &i[0]; //übrigens liefert der name eines Array, also 
                         //ohne Klammern auh die adresse zurück
                         //also ist dies hier auch so möglich: 
                         // pointer_auf_i = i;

  j = *(i+2) * *(i+8);
  
  printf("%i * %i = %i\n", *(i+2),*(i+8), j);

  }

Autor: Michal (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
  }

Autor: Marvin M. (Gast)
Datum:

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

Jawoll.

Autor: franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michal (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

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

Grüße

Michal

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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. ;-)

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
a[i] = *(a + i) = *(i + a) = i[a]
char *str = "abXde";
int idx = 2;

char c;

/* 
  Die folgenden Zeilen weisen der Variablen c ein 'X' zu
  und sind gültiges C:
*/

c = 'X';
c = str[2];
c = str[idx];
c = "abXde"[2];
c = "abXde"[idx];
c = 2[str];
c = idx[str];
c = idx["abXde"];
c = 2["abXde"];
c = *(str + 2);
c = *(2 + str);

Autor: franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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"

Autor: Christian L. (lorio)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven P. schrieb:

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

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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Christian L. (lorio)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.