Seite 1 von 1

Hilfe bei Zeiger

Verfasst: So Jan 12, 2014 11:08 am
von patrickk83
Hallo Leute!

Meine letzten C-Programme liegen schon einige Jahre zurück. Ich bin auf einen programmcode gestoßen, der
mir nicht ganz logisch bzw. richtig erscheint. Aber wie gesagt, ich versuche gerade wieder meine Kentnisse neu
aufzufrischen. Mit den Zeigern hatte ich zu Schulzeiten schon so meine Schwierigkeiten bzw. dieses Thema war für
uns für das Programmieren von uControllern scheinbar nicht wirklich relevant. Aber egal. Ich füge mal ein paar kurze
Code-Zeilen an und würde gerne eure Meinung darüber erfahren (die Zeilen sind nicht geordnet und sollen nur zum Verständnis erklärt werden).

Code: Alles auswählen

1: unsigned int x=0;
2: unsigned char a[512];
3: unsigned char *zeiger = a + (sizeof(a)/2);
4: zeiger--;
5: if (zeiger > a + sizeof(a)) zeiger++[0] = x;
Zeile 3: Hier wird doch keine Adresse übergeben sondern ein Wert oder irre ich mich? Müsste
hier nicht & (a + (sizeof(a)/2)) stehen damit der Zeiger auf eine Adresse zeigt?
Zeile 4: Wird hier die Adresse, auf die der Zeiger verweist, dekrementiert?
Zeile 5: Diese Zeile verwirrt mich komplett. Müsste hier nicht der * Operator davor?

Vielen Dank für eure Hilfe,

mfG Patrick

Re: Hilfe bei Zeiger

Verfasst: So Jan 12, 2014 11:34 am
von Xin
patrickk83 hat geschrieben:Hallo Leute!

Meine letzten C-Programme liegen schon einige Jahre zurück. Ich bin auf einen programmcode gestoßen, der
mir nicht ganz logisch bzw. richtig erscheint. Aber wie gesagt, ich versuche gerade wieder meine Kentnisse neu
aufzufrischen. Mit den Zeigern hatte ich zu Schulzeiten schon so meine Schwierigkeiten bzw. dieses Thema war für
uns für das Programmieren von uControllern scheinbar nicht wirklich relevant. Aber egal. Ich füge mal ein paar kurze
Code-Zeilen an und würde gerne eure Meinung darüber erfahren (die Zeilen sind nicht geordnet und sollen nur zum Verständnis erklärt werden).

Code: Alles auswählen

1: unsigned int x=0;
2: unsigned char a[512];
3: unsigned char *zeiger = a + (sizeof(a)/2);
4: zeiger--;
5: if (zeiger > a + sizeof(a)) zeiger++[0] = x;
Zeile 3: Hier wird doch keine Adresse übergeben sondern ein Wert oder irre ich mich? Müsste
hier nicht & (a + (sizeof(a)/2)) stehen damit der Zeiger auf eine Adresse zeigt?
a wird wie ein Zeiger behandelt. a entspricht &a[0]. sizeof(a) ist 512, das ganze durch 2 ist 256. a+256 entspricht a[256] oder - wie ich es an Zeile 5 sehe, magst Du es lieber kryptisch: 256[a] wäre auch okay. ;-)
Zeile 4: Wird hier die Adresse, auf die der Zeiger verweist, dekrementiert?
Adressen sind immer Konstant. Der Wert, auf den Zeiger zeigt, bleibt unverändert, denn da steht nur Zeiger, also wird auch Zeiger dekrementiert. Zeiger zeigt anschließend auf a[255].

Möchtest du den Wert verändern, muss der Zeiger dereferenziert werden: (*zeiger)--
Zeile 5: Diese Zeile verwirrt mich komplett. Müsste hier nicht der * Operator davor?
Wenn Dich eine Zeile verwirrt, ändere sie.
Mich verwirrt sie auch und ich programmiere seit 20 Jahren C und C++.

Sowas sollte man entsprechend refactoren.

Code: Alles auswählen

if (zeiger > a + sizeof(a)) 
    zeiger++[0] = x;
Die gewünschte Aussage ist vermutlich, dass Zeiger nicht über das Array hinauslaufen soll. Du fragst auf größer ab: Die Zuweisung findet also nur dann statt, wenn hinter das Array geschrieben werden soll. Gewünscht ist also vermutlich Zeiger < a + sizeof(a).


zeiger++ bedeutet, dass der Zeiger erhöht wird, aber der ursprüngliche Wert zurückgegeben wird und nicht der erhöhte.
Zeiger zeigt auf das 255. Nach der Operation zeigt Zeiger auf das 256. Element, aber das Resultat von Zeiger++ ist ein Zeiger auf das 255. Element. Darauf wird zugegriffen: a[255] = x.

Eselsbrücke: C++ gibt den gleichen Wert zurück wie C. Eigentlich müsste die Sprache ++C heißen, damit sie einen höheren Rückgabewert hat, nämlich den, den C nach der Inkrementierung besitzt.

Re: Hilfe bei Zeiger

Verfasst: So Jan 12, 2014 11:59 am
von cloidnerux
Zeile 3: Hier wird doch keine Adresse übergeben sondern ein Wert oder irre ich mich? Müsste
hier nicht & (a + (sizeof(a)/2)) stehen damit der Zeiger auf eine Adresse zeigt?
Die Addressen, die ein Pointer beinhaltet sind auch nur Zahlen.
Wenn ein Pointer auf irgendetwas Zeigt, hat er eine Adresse, die irgendeine Zahl ist, wie in int. Der Unterschied ist nur, wie diese zahl behandelt wird. Bei einem int wird der Wert als Wert behandelt, bei einem Pointer wird der Wert als Adresse im Speicher behandelt.
Was in dieser Zeile passiert ist, du nimmst den Wert der Adresse von a[0] und addierst die hälfte der Arraylänge drauf. Da das ein Byte-Array ist, liegt damit der Pointer auf dem 256tem Element in dem Array.
Zeile 4: Wird hier die Adresse, auf die der Zeiger verweist, dekrementiert?
Jop. Selbes spiel. Du hast einen Wert, den kann man Dekrementieren und inkrementieren. Was bei Pointer besonders ist, soweit ich mich erinnere, wird nicht immer um 1 hoch oder runtergezählt, sondern um die Byte-Größe des Datentyps.
Zeile 5: Diese Zeile verwirrt mich komplett. Müsste hier nicht der * Operator davor?
Das geschieht durch den Indexoperator ([]).

Insgesamt ist dieser Sourcecode nicht sehr sinnvoll, hier wollte euch wer eine Denkaufgabe stellen?

Re: Hilfe bei Zeiger

Verfasst: So Jan 12, 2014 12:05 pm
von Xin
cloidnerux hat geschrieben:Was bei Pointer besonders ist, soweit ich mich erinnere, wird nicht immer um 1 hoch oder runtergezählt, sondern um die Byte-Größe des Datentyps.
Du erinnerst Dich richtig :-)

Code: Alles auswählen

unsigned int array[2];
unsigned int * p = array;
unsigned int * p0;

printf( "a[0]: %p\n", (void *) p);
p0 = p++;  // alter Wert wird zurückgegeben
printf( "a[1]: %p\n", (void *) p);

printf( "Diff: %d   Size: %s\n", p-p0, sizeof( unsigned int ) );

Re: Hilfe bei Zeiger

Verfasst: So Jan 12, 2014 12:08 pm
von patrickk83
Vielen Dank für Eure ausführliche Hilfestellung.

Jetzt ist mir einiges klarer geworden.

@cloidnerux: Es handelt sich tatsächlich um eine Denkaufgabe :-) Es handelt sich um einen Programmcode bei dem
ich eine Schwachstelle im Code erkennen soll

Vielen Dank,

mfG Patrick

Re: Hilfe bei Zeiger

Verfasst: So Jan 12, 2014 12:11 pm
von patrickk83
@Xin: Warum muß (void *) p bei printf angegeben werden?

Code: Alles auswählen

printf( "a[0]: %p\n", (void *) p);

Re: Hilfe bei Zeiger

Verfasst: So Jan 12, 2014 12:50 pm
von cloidnerux
Warum muß (void *) p bei printf angegeben werden?
Das ist ein Cast, du zwingst den Compiler diesen Datentyp wie einen anderen zu behandeln.
Bei Pointern macht das aber keinen sinn, denn alle Pointer sind vom Typ her das selbe(Typ Pointer), lediglich der Typ auf den es zeigt ändert sich.
Hier den Pointer zu einem void Pointer zu casten ist unnötig.

Der void-Pointer existiert und dient dazu, Pointer zu kennzeichnen, deren Datentyp unbestimmt ist, z.B wenn du per malloc Speicher reservierst. Man muss dann selber zusehen, den Pointer auf einen konkreten Datentyp zu setzten.

Re: Hilfe bei Zeiger

Verfasst: So Jan 12, 2014 1:08 pm
von Xin
patrickk83 hat geschrieben:@cloidnerux: Es handelt sich tatsächlich um eine Denkaufgabe :-) Es handelt sich um einen Programmcode bei dem
ich eine Schwachstelle im Code erkennen soll
Dann habe ich wohl etwas zu weit vorgegriffen. ^^

patrickk83 hat geschrieben:ointern macht das aber keinen sinn, denn alle Pointer sind vom Typ her das selbe(Typ Pointer), lediglich der Typ auf den es zeigt ändert sich.
Hier den Pointer zu einem void Pointer zu fasten ist unnötig.
Nicht ganz... der G++ meckert das bei mir an, dass für %p ein (void *) gewünscht ist und ein (whatsoever *) eben kein (void *) ist.

Allerdings programmiere ich in der Regel C++, das wird vermutlich eine Warning sein, die der C++-Compiler meldet, der C-Compiler sollte sich hier eigentlich ruhig verhalten. Gewohnheit.

Re: Hilfe bei Zeiger

Verfasst: So Jan 12, 2014 1:21 pm
von patrickk83
Danke nochmals!

Werde sicher wieder mal um Hilfe bitten hier im Forum.

@cloidernux: Verstehe jetzt die Problematik des gesamten Codes. Darum ging es ja prinzipiell.

MfG Patrick

Re: Hilfe bei Zeiger

Verfasst: So Jan 12, 2014 1:24 pm
von Xin
patrickk83 hat geschrieben:Werde sicher wieder mal um Hilfe bitten hier im Forum.
Kein Thema. Grundsätzlich ist auch weiterlernen und später anderen helfen gerne gesehen ;-)