C für PICs: Pointer



zurück zu C für PICs , C-Compiler , PIC-Prozessoren , Elektronik , Homepage

C für PICs
Grundlagen von C
Variablen
Funktionen
Operationen
Programmablaufsteuerung
Arrays und Strings
Pointer
Strukturierte Typen
PIC-spezifisches


zurück zu C für PICs


Pointer

Ein Pointer ist eine Variable, die eine Speicheradresse des Prozessors enthält. Das kann eine Adresse des Datenspeichers oder eine Adresse des Programmspeichers sein. Pointer verwendet man, um auf Variablen (Datenspeicher) oder Funktionen (Programmspeicher) flexibel zugreifen zu können.


Pointer: Allgemeines

Ein Pointer ist eine Variable, und wird auch wie eine solche Deklariert. Dabei wird angegeben, auf was für einen Typ dieser Pointer zukünftig verweisen soll. Um den Pointer als solchen zu kennzeichnen, wird seinem Namen bei der Deklaration ein "*" vorangestellt:

typ *Pointername;

Ich deklariere nun einen Pointer, der auf Interer-Variablen zeigen kann.

int *Zeiger;

Um nun dem Pointer mit der Adresse einer existierenden Variablen zu beschreiben, muss man natürlich die Adresse dieser Variable erst mal herausbekommen. Dafür gibt es in C den &-Operator, der einer normalen Variable direkt vorangestellt wird, um deren Adresse zu ermitteln.

int *Zeiger;
int EchteVariable;
Zeiger = &EchteVariable;

So, nun steht in Zeiger die Adresse von EchteVariable. Was habe ich davon? Man kann nun auf den Wert von EchteVariable auch mit Hilfe des Pointers Zeiger zugreifen. Dazu muss man C anweisen, auf die Integer-Variable zuzugreifen, auf die Zeiger zeigt. Dazu wird dem Pointer-Namen ein "*" vorangestellt. Man kann jetzt also anstelle von "EchteVariable" auch "*Zeiger" schreiben.

EchteVariable = 5;
int AndereVariable;
AndereVariable = *Zeiger;


Mit Pointern lässt sich nur in beschränktem Umfang rechnen. Es gibt (außer &, *) nur Addition (+), Subtraktion (-), Increment (++) und Decrement (--). Increment und Decrement vergrößern oder Verkleiner den Wert eines Pointers jeweils um die Speichergröße des Typs, auf den er zeigt. Der integer-Pointer aus dem obigen Beispiel würde bei einem Increment (Zeiger++) um den Wert 2 erhöht werden, da Integer 2 Byte groß ist.



Pointer und Arrays

Pointer und Arrays haben mehr gemeinsam, als man zunächst einmal denken mag. Während die Array-Variable mit einem Index ein bestimmtes Element des Arrays darstellt, ist die Array-Variable ohne Index nur ein Pointer auf das erste Element des Arrays. Das folgende Beispiel mag das verdeutlichen.

int Feld[10];
Feld[3] = 5;
int *Zeiger;
Zeiger = Feld;
int Ergebnis;
Ergebnis = Zeiger[3];

Ich deklariere das Array "Feld" und belege dessen Element Nr 3 mit dem Wert 5. Die anderen Elemente sind mir mal egal. Dann deklariere ich einen Pointer mit dem Namen "Zeiger". Anschließend weise ich diesem Pointer Feld zu. Da ich Feld ohne einen Index verwende, stellt Feld einen Pointer auf das erste Element des Arrays da. Damit zeigt Zeiger nun auf den Anfang von Feld.

Ich hätte natürlich auch einen Zeiger auf das erste Element von Feld verwenden können. Das wäre Feld[0] gewesen. Da Feld[0] aber kein Zeiger ist (sondern eine Integer-Variable) hätte ich schreiben müssen:
Zeiger = &Feld[0];

Da ist es dann doch einfacher direkt Feld zu verwenden. Abschließend sieht man, wie ich nun Zeiger wie ein Array verwende, um auf ein einzelnes Element von Feld zuzugreifen. Es handelt sich um das Element Nr 3, in dem vorab ja der Wert 5 gespeichert wurde.

Das hier beschriebene erklärt auch, warum man nicht einfach ein Array in ein anderes Array kopieren kann. Das Kopieren muss stets elementweise erfolgen.

int a[100], b[100];
...
a = b;                                  // FALSCH
char i;
for (i=0; i<100; i++) a[i] = b[i];      // RICHTIG




Pointer und Funktionen

Schon vorher wurde beschrieben, wie Argumente an Funktionen übergeben werden können, und wie man ein Argument von einer Funktion zurückerhalten kann.
Eine dritte Alternative besteht darin, dass man der Funktion als Argument den Pointer auf eine Variable übergibt.

Was bringt das?
Wenn ich möchte, dass eine Funktion einen Variablenwert verändert, dann muss ich diesen Wert zunächst an die Funktion als Argument übergeben, und das zurückgegebene Argument der ursprünglichen Variablen wieder zuweisen. Dazu muss die Variable zwei mal kopiert werden, was Zeit kostet.

int Doppel (int a)
{
    return (a << 1);
}

void main (void)
{
    int b;
    b = 1;
    b = Doppel(b);   // <-- hier wird 2 mal kopiert
}

Bei einer einzelnen integer-Variable fällt das kaum ins Gewicht. Oftmals werden aber umfangreiche strukturierte Variablen übergeben. Diese je zwei mal zu kopieren kostet nicht nur Zeit, sondern auch Speicherplatz. Es muss ja eine lokale Kopie dieser großen Variablen angelegt werden. Im begrenzten PIC-Arbeitsspeicher kann es da schnell eng werden.

Wenn man aber der Funktion nur die Speicheradresse dieser großen Variable übergibt, dann kann die Funktion diese Variable direkt verändern. Eine Argument-Rückgabe ist überflüssig.

void Doppel (int *a)
{
    *a << 1;
}

void main (void)
{
    int b;
    b = 1;
    Doppel(&b);
}

Anstelle von einzelnen Variablen wird man Arrays, Strings oder strukturierte Variablen übergeben. Die werden in C ohnehin als Pointer verwaltet, so dass sich hier sogar das vorgestellt & bei der Parameterübergabe erübrigt.

void Loesche (int *a)
{
    char c;
    for (c=0; c<10; c++)
    {
       *a = 0;
       a++;
    }
}

void main (void)
{
    int b[10];
    Loesche(b);
}






--> weiter zu strukturierten Typen
nach oben

zurück zu C für PICs , C-Compiler , PIC-Prozessoren , Elektronik , Homepage



Autor: sprut
erstellt: 01.10.2007
letzte Änderung: 01.10.2007