Pointer Hilfe!

Die Programmiersprache C# und Programmierung im .NET Framework/Mono
Antworten
wing354

Pointer Hilfe!

Beitrag von wing354 » Mo Sep 14, 2015 5:20 pm

Moin,
ich übe gerade für meine Klausur Informatik für Ingenieure, es geht hauptsächlich um die Programmiersprache C.

Nun hab ich in einer Altklausur zwei Aufgaben zu Pointern gefunden und ich finde einfach keine Lösung für das Problem...

Gegeben sind die folgenden Programme:

Code: Alles auswählen

/* Programm 1 */

#include <stdio.h>

int main(){
	char a[8];
	char *b;
	int i;
	
	b = a;
	
	for (i=0;i<8;i++){
		*b++ = 0xff - i;
	}
}
und

Code: Alles auswählen

/*Programm 2 */

#include <stdio.h>

int main(){
	char x[4];
	char *y;
	char u[4];
	char *v;
	
	int i;
	
	y = x;
	for(i=0;i<4;i++){
		*y++ = i%2;
	}
	
	v = u + (y-x);
	
	while(v != u) {
		*--v = *--y;
	}
	return;
}
Die Aufgabenstellung lautet für das 1. Programm: mit &a = 0x00001000 und &b = 0x00002000
Notieren Sie den Speicherinhalt an folgenden Adressen in 4 Blöcken a 1 Byte in Hexadezimaldarstellung, wenn das Programm vollständig durchlaufen wurde.

Code: Alles auswählen

Adresse       | Byte 4 | Byte 3 | Byte 2 | Byte 1
0x00001000 |  ...     |    ...   |     ...  |  ...
0x00001004 | ...      |    ...   |    ...   |  ...
0x00002000 | ...      |    ...   |    ...   |  ...
Beim zweiten Programm ist die Aufgabenstellung ähnlich nur, dass dieses mal gegeben ist: x = 0x00001000 , &y = 0x00002000 , u = 0x00003000 und
&v = 00004000

Ich verstehe an sich das grundlegende Prinzip von Pointern, aber mir ist schleierhaft wie sich die Speicherinhalte zusammensetzen sollen, außer beim zweiten Programm für die Adressen 0x00002000 und 0x00004000.

Ich wäre sehr dankbar, wenn mir jemand erklären könnte wie ich am besten bei einer Aufgabenstellung wie dieser vorgehen muss, um sie korrekt lösen zu können.

Konkret hakt es bei den Zeilen: Programm 1: *b++ = 0xff - i;
und bei Programm 2: for(i=0; i<4;i++){*y++ = i % 2;}
sowie while(v != ) { *--v = *--y;}
Ich verstehe nicht was diese Zeilen bewirken...

Mit freundlichem Gruß
wing354

Edit by Xin: Codetags hinzugefügt

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Pointer Hilfe!

Beitrag von Xin » Mo Sep 14, 2015 9:04 pm

Moin wing,

wir sind kein anonymes Forum. Wir freuen uns über Beteiligung, fragen bei der Registrierung keine wichtigen persönlichen Informationen ab, aber wir erwarten dass Personen ansprechbar sind.
wing354 hat geschrieben: Ich wäre sehr dankbar, wenn mir jemand erklären könnte wie ich am besten bei einer Aufgabenstellung wie dieser vorgehen muss, um sie korrekt lösen zu können.
Das kann ich Dir gerne erklären und ich gehe davon aus, das auch bereits getan zu haben.
Damit ich das nicht alles neu schreiben muss, würde ich Dich bitten folgende Lektionen aus dem C-Kurs zu lesen: Arrays und die nachfolgenden beiden Lektionen. Im Idealfall liest Du den kompletten Kurs, insbesondere den Bereich mit den Ausdrücken, damit wir das gleiche Vokabular benutzen.
wing354 hat geschrieben:Konkret hakt es bei den Zeilen: Programm 1: *b++ = 0xff - i;
0xff - i ist ein Ausdruck, der eine Zahl zurück gibt. 255 - i. Diese Zahl wird irgendwo hin zugewiesen und zwar nach *b++. Das wird so *(b++) ausgeführt. b++ bedeutet, dass der Pointer um 1*sizeof(char) erhöht wird (also 1 Byte weiter), aber es wird der alte Wert von b zurückgegeben. Was also vorher in b drin gestanden hat, wird zurückgegeben, aber b ist nach der Anweisung um 1 erhöht.
In b steht ein Zeiger, der nach (b++) auch genauso wieder zurück gegeben wird. Auf diesen Zeiger wird zugegriffen: *(b). Das bedeutet, dass da, wo b ursprünglich hinzeigte nun die Zahl geschrieben wird.
Wenn das ++ nach der Variablen steht, wird erst die Variable zurückgegeben und anschließend noch erhöht.
wing354 hat geschrieben:und bei Programm 2: for(i=0; i<4;i++){*y++ = i % 2;}
Das gleiche Problem, nur mit einer anderen Zahl und einem anderen Variablennamen.
wing354 hat geschrieben: sowie while(v != ) { *--v = *--y;}
Ich verstehe nicht was diese Zeilen bewirken...
while( v != u )

Ähnliches Problem, aber hier steht das -- vor der Variablen. Es wird also erst reduziert und dann der Wert der Variablen zurück gegeben. --y ist also der Zeiger vor dem ursprünglichen Wert von y. Auf diesen Zeiger vor dem ursprünglichen y wird dann mit * zugegriffen, es das Char aus der Adresse herausgelesen und stellt den rechten Teil der Gleichung dar. Genau sieht es auf der linken Seite aus. v wird reduziert, gibt den reduzierten Zeiger zurück, auf den zugegriffen (*) werden soll. Da dieser Zeiger allerdings links vom =-Operator steht, wird der Char, der bei *--y herauskommt dahin (*) geschrieben, wohin --v zeigt.
In Kombination mit der while-Schleife wird also solange rückwärts kopiert, bis v == u ist.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

wing354
Beiträge: 8
Registriert: Di Sep 15, 2015 8:07 pm

Re: Pointer Hilfe!

Beitrag von wing354 » Di Sep 15, 2015 8:22 pm

Moin und danke für deine schnelle Antwort!

Wenn ich das richtig verstanden habe, dann komme ich auf folgende Lösungen für das 1. Prgramm:

Adresse | Byte 4 | Byte 3 | Byte 2 | Byte 1
0x00001000 | 0xfc | 0xfd | 0xfe | 0xff
0x00001004 | 0xfb | 0xfa | 0xf9 | 0xf8
0x00002000 | 0x00 | 0x00 | 0x10 |0x04
,weil zunächst die 255 8mal heruntergezählt wird inklusive -0, sodass ich 8 Bytes fülle, ist das korrekt?

und bei Programm 2 komme ich auf die folgenden Lösungen:
Adresse | Byte 4 | Byte 3 | Byte 2 | Byte 1
0x00001000 | 0x01 | 0x00 | 0x01 | 0x00
0x00002000 | 0x00 | 0x00 | 0x10 | 0x00
0x00003000 | 0x01 | 0x00 | 0x01 |0x00
0x00004000 | 0x00 | 0x00 | 0x30 |0x00
,weil zunächst die Operationen 0mod2=0, 1mod2=1,2mod2=0, 3mod2=1 gebildet werden, und anschließend mit der "while" - Bedingung y in v kopiert werden.

Hab ich das richtig verstanden?

und nochmal eine grundlegende Frage, wenn ich einen Pointer habe und die Operation *y++ heißt, dann erhöhe ich den Inhalt auf den der Pointer zeigt, wenn ich jedoch y++ erhöhe ich die Adresse auf die der Pointer zeigt, um die Größe dessen Typ Pointer besitzt, korrekt?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Pointer Hilfe!

Beitrag von Xin » Di Sep 15, 2015 9:40 pm

wing354 hat geschrieben:Wenn ich das richtig verstanden habe, dann komme ich auf folgende Lösungen für das 1. Prgramm:

Adresse | Byte 4 | Byte 3 | Byte 2 | Byte 1
0x00001000 | 0xfc | 0xfd | 0xfe | 0xff
0x00001004 | 0xfb | 0xfa | 0xf9 | 0xf8
0x00002000 | 0x00 | 0x00 | 0x10 |0x04
,weil zunächst die 255 8mal heruntergezählt wird inklusive -0, sodass ich 8 Bytes fülle, ist das korrekt?
Warum gehst Du in der ersten Reihe nach links runter, in der zweiten nach rechts runter?
Wenn Du 8 mal herunterzählst, zählst Du b doch auch 8 mal hoch, oder?

Erzählte Dein Lehrer was von Big-Endian und Little-Endian?
wing354 hat geschrieben:und bei Programm 2 komme ich auf die folgenden Lösungen:
Adresse | Byte 4 | Byte 3 | Byte 2 | Byte 1
0x00001000 | 0x01 | 0x00 | 0x01 | 0x00
0x00002000 | 0x00 | 0x00 | 0x10 | 0x00
0x00003000 | 0x01 | 0x00 | 0x01 |0x00
0x00004000 | 0x00 | 0x00 | 0x30 |0x00
,weil zunächst die Operationen 0mod2=0, 1mod2=1,2mod2=0, 3mod2=1 gebildet werden, und anschließend mit der "while" - Bedingung y in v kopiert werden.

Hab ich das richtig verstanden?
Ja, das sieht gut aus, ich habe mir das gerade kurz angeguckt und komme auf das gleiche Ergebnis, bevor ich mir Dein Ergebnis angesehen habe.
Hast Du das Programm denn mal getestet?
wing354 hat geschrieben:und nochmal eine grundlegende Frage, wenn ich einen Pointer habe und die Operation *y++ heißt, dann erhöhe ich den Inhalt auf den der Pointer zeigt, wenn ich jedoch y++ erhöhe ich die Adresse auf die der Pointer zeigt, um die Größe dessen Typ Pointer besitzt, korrekt?
Schau Dir dieses Programm an:

Code: Alles auswählen

#include <stdio.h>

int main()
{
  int x[10] = {0};
  int * y = x;

  printf( "%p: %d %d %d %d %d\n", (void*) y, x[0], x[1], x[2], x[3], x[4] );
  y++;
  printf( "%p: %d %d %d %d %d\n", (void*) y, x[0], x[1], x[2], x[3], x[4] );
  *y++ = 2;
  printf( "%p: %d %d %d %d %d\n", (void*) y, x[0], x[1], x[2], x[3], x[4] );
  (*y)=3;
  printf( "%p: %d %d %d %d %d\n", (void*) y, x[0], x[1], x[2], x[3], x[4] );
  (*y)++;
  printf( "%p: %d %d %d %d %d\n", (void*) y, x[0], x[1], x[2], x[3], x[4] );
}
mit dem Ergebnis:

Code: Alles auswählen

xin@trinity:~/xsd/apps/gsys$ ./a.out 
0x7ffe1b85d780: 0 0 0 0 0
0x7ffe1b85d784: 0 0 0 0 0
0x7ffe1b85d788: 0 2 0 0 0
0x7ffe1b85d788: 0 2 3 0 0
0x7ffe1b85d788: 0 2 4 0 0
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

wing354
Beiträge: 8
Registriert: Di Sep 15, 2015 8:07 pm

Re: Pointer Hilfe!

Beitrag von wing354 » Mi Sep 16, 2015 5:44 pm

Oh, das war nicht gewollt, ich wollte die Reihenfolge der Bytes beibehalten und nicht vertauschen.

Wenn ich die Programme teste, dann komme ich auch auf die passenden Lösungen!

Verstehe ich dein Programm richtig? Du initialisierst zunächst ein Array mit der Länge zehn und speicherst in jedes Element eine "Null",
danach lässt du einen Pointer auf dieses Feld zeigen. Anschließend lässt du die Adresse auf die y zeigt anzeigen und die ersten fünf Elemente von x, die alle Null sind. Dann erhöhst du die Adresse auf die y zeigt um den Typ 1*sizeof(int), also um vier. Danach lässt du dir wieder die Adresse Anzeigen auf die y zeigt und erneut die ersten fünf Elemente von x anzeigen, welche ja immer noch Null sind. Anschließend lässt du mit y auf das Element von x[1] zeigen und speicherst darin die 2. Die Zeile danach verstehe ich nicht genau, weil ich davon ausgehe, dass y immer noch auf x[1] zeigt und deshalb die 3 da gespeichert werden müsste meiner Meinung nach, aller die wird die 3 ja in x[2] gespeichert, wieso? Zu guter letzt erhöhst du den Inhalt auf den aktuell y zeigt, nämlich x[2] um 1, das heißt auf vier.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Pointer Hilfe!

Beitrag von Xin » Mi Sep 16, 2015 11:16 pm

wing354 hat geschrieben:Die Zeile danach verstehe ich nicht genau, weil ich davon ausgehe, dass y immer noch auf x[1] zeigt und deshalb die 3 da gespeichert werden müsste meiner Meinung nach, aller die wird die 3 ja in x[2] gespeichert, wieso?
Das vorherige *y++ erhöht den Zeiger, aber zurückgegeben wird der ursprüngliche Zeiger. Der ursprüngliche Zeiger wird dann mit * dereferenziert, um die 2 dorthin zu schreiben. Nach der Operation zeigt der Zeiger aber auf das nachfolgende Element, so dass die drei nach der 2 geschrieben wird.

Spiele mit solchen Experimenten, das hilft Dir beim Verständnis.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

wing354
Beiträge: 8
Registriert: Di Sep 15, 2015 8:07 pm

Re: Pointer Hilfe!

Beitrag von wing354 » Do Sep 17, 2015 9:25 am

Ich glaube jetzt hab ich es kapiert, aber das ist natürlich eine gute Idee damit ein wenig damit rumzuspielen, um ein besseres Verständnis dafür zu bekommen!

Aber vielen Danke für deine Hilfe, du hast mir wirklich sehr geholfen!
Wenn ich nochmal eine Frage hab, dann melde ich mich wieder.

Antworten