ein Kapitel zurück                                           ein Kapitel weiter

Wenn sie jetzt dachten das war es, dann muss ich sie leider Enttäuschen. Das Kapitel der Zeiger ist sehr umfangreich und vor allem für Anfänger sehr schwer verständlich. Und leider wird die Sache mit den Zeigern, zumindest für Anfänger jetzt noch komplizierter.

Jetzt kommen wir zu den Zeigern und Arrays. Also Zeigern und Variablen mit Indexfeldern. Bei unseren Programmen vorher haben unsere Zeiger noch nicht viel Sinn gehabt. In dem Programmbeispiel das jetzt kommt können wir mit Hilfe eines Zeigers auf die einzelnen Elemente unseres Arrays zeigen...

/*Download:zei1.c*/
#include <stdio.h>

int main()
{
int element[8]= {1,2,4,8,16,32,64,128};
int *ptr;
int i;

ptr=element;

printf("Der Wert auf den *ptr zeigt ist %d\n",*ptr);
printf("Durch *ptr+1 zeigt er jetzt auf %d\n",*(ptr+1));
printf("Jetzt zeigt *ptr durch *(ptr+3) auf %d\n",*(ptr+3));

printf("\nJetzt alle zusammen : \n");

for(i=0; i<8; i++)
printf("element[%d]=%d \n",i,*(ptr+i));

return 0;
}

Das erste was sie sich jetzt Fragen werden, wieso wir bei......

ptr=element;

keinen Adressoperator verwenden. Bevor ich zur großen Erklärung ansetzen fügen sie doch mal vor unserem 'return 0;' folgendes ein....

............
printf("%d\n",*element);
printf("%d",ptr[0]);

return 0;
}


Wenn sie das Programm anschließend ausführen werden diese beiden neuen Eingaben beide den Wert '1' ausgeben, also das erste Element unseres Arrays. Daraus können wir ziehen das...

*Pointer Daselbe ist wie Pointer[0]

und

*(Pointer+2) ist Daselbe wie Pointer[2]

Wir hätten die Adresse unseres Array genauso gut so übergeben können.....

ptr=&elemement[0];

Auf beide Arten übergeben wir unserem Zeiger die Adresse des ersten Arrays mit dem Index [0]. Was die Ausgabe der 1.Zeile dann auch bestätigt. Dazu auch der Programmtechnische Beweis....

/*Download:zei2.c*/
#include <stdio.h>

int main()
{
int element[8]= { 1,2,4,8,16,32,64,128};
int *ptr;

ptr=element;

printf("%p : %d\n",*element,*element);
printf("%p : %d\n",ptr[0],ptr[0]);

return 0;
}

Die nächste Anweisung lautet...

*(ptr+1);

Und ausgegeben wird tatsächlich der nächste Wert unseres Array 'element' nämlich die 2 ausgegeben. Also 'element[1]'. Wieso das so ist möchte ich Ihnen wieder anhand einer Tabelle erklären.....



Unsere Tabelle soll unser Array zeigen wie es unsere Rechner sieht. Unsere Arrays sind gespeichert in der Adresse von $004 - $032 und hat eine Gesamtgröße von 32 Bytes (auf 16Bit-Systemen 16 Bytes). Ein Element hat die Größe von 4 Bytes, da 'int' nun mal vier Bytes groß ist (auf 32Bit-Rechnern). Daher ist auch die Adressierung immer in 4er Schritten voneinander entfernt (Ich habe hier die Adressen zum leichteren Verständnis als dezimale Adressen und nicht wie üblich als hexdezimale Adressen dagestellt). Nun durch...

ptr=element oder ptr=&element[0]

...sieht unser Zeiger folgendermaßen aus....



Jetzt wird durch...

*(ptr+1);

...praktisch die Adresse $004 um 4 erhöht. Wieso? Nun unser Zeiger wurde am Anfang unseres Programms vom Typ 'int' angegeben. Und der Typ 'int' hat die Größe von 4 Byte (Systemabhängig). Genauso läuft es übrigens beim Array 'intern' auch ab wenn der Indexzähler erhöht wird. Damit unser Zeiger auch tatsächlich auch auf die nächste Adresse zeigt, muss ptr+1 zwischen Klammern stehen. Das daher weil Klammern eine höhere Bindungskraft als der Dereferenzierungsoperator haben und somit zuerst ausgewertet wird. Sollten sie z.B. die Klammern vergessen, würden sie nicht auf die nächste Adresse zeigen, sondern den Wert auf den der Zeiger 'ptr' zeigt um eins erhöhen.
Nun zurück zum Programm. Jetzt zeigt unser Zeiger ptr auf....



Jetzt folgt...

printf("Jetzt zeigt *ptr durch *(ptr+3) auf %d\n",*(ptr+3));

Hiermit erhöhen wir den Wert unserer Adresse auf $020. Deshalb wird auch der Wert 16 ausgegeben. Nun wir gehen davon aus das alles mit rechten Dingen zugegangen ist und daher folgende Tabelle....



Ich möchte es hiemit bei der Erklärung diese Programms belassen und hoffe es so verständlich wie möglich ausgedrückt zu haben.

Um Missverständnisse für die nächsten Kapitel zu vermeiden möchte ich noch schnell die Beziehung zwischen Zeiger und Array klären. Oben im Programm haben sie gelesen das *ptr und elemente[0] dasselben sind. Nun ganz richtig ist das nicht. Mit.......

int elemente[8];

...wird während der Übersetzungszeit, Speicher für 8 int-Werten reserviert. Mit.....

int *ptr;

...wurde ein Zeiger definiert der nur auf eine (Anfangs)Adresse vom Typ int zeigen kann. Der Zeiger ptr kann im Gegensatz zum Array elemente keine 8 Elemente aufnehmen, sondern nur auf eines der 8 zeigen. Bis jetzt und die nächsten Kapitel dürften Zeiger für sie noch nicht viel Sinn ergeben. Denn alles was wir bis jetzt mit Diesen gemacht haben könnten wir leicht auch ohne machen.

Hierzu noch ein Beispiel zum Studieren....

/*Download:zei3.c*/
#include <stdio.h>

float dm[4]={9.99,12.99,16.99,19.99};
float euro[4]={5.50,6.67,8.50,10.01};
float Dollar[4]={3.33,4.25,6.00,7.33};
float *ptr;

void ausgabe(char w)
{
int i;
for(i=0; i<4; i++)
printf("Produkt %d kostest %.2f %c\n",i+1,*(ptr+i),w);
printf("\n");
}


int main()
{
int abfrage;
printf("\tPreislisten\n\n");

do{
printf("-1- Preisliste in DM\n");
printf("-2- Preisliste in Euro\n");
printf("-3- Preisliste Dollar\n");
printf("-4- Programm beenden\n");
printf("\nIhre Auswahl : ");
scanf("%d",&abfrage);

switch(abfrage)
{
case 1 : ptr=dm;
ausgabe('M');
break;
case 2 : ptr=euro;
ausgabe('E');
break;
case 3 : ptr=Dollar;
ausgabe('$');
break;
default: break;
}
}while(abfrage<4);

return 0;
}

Ich gebe es zu bisher haben Zeiger noch nicht allzu viel Sinn gemacht. Alles was wir mit Zeigern bisher gemacht haben hätten wir auch ohne diese Bewerkstelligen können. Diese Kapitel dienen auch dazu mehr oder weniger sie langsam an dieses Thema heranzuführen. Spätestens wenn es um dynamischen Speicherverwaltung geht werden sie merken wie Sinnvoll Zeiger sind.

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf