Hilfe bei Zeiger

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
patrickk83
Beiträge: 4
Registriert: So Jan 12, 2014 10:31 am

Hilfe bei Zeiger

Beitrag von patrickk83 » So Jan 12, 2014 11:08 am

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

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

Re: Hilfe bei Zeiger

Beitrag von Xin » So Jan 12, 2014 11:34 am

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

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Hilfe bei Zeiger

Beitrag von cloidnerux » So Jan 12, 2014 11:59 am

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?
Redundanz macht wiederholen unnötig.
quod erat expectandum

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

Re: Hilfe bei Zeiger

Beitrag von Xin » So Jan 12, 2014 12:05 pm

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

patrickk83
Beiträge: 4
Registriert: So Jan 12, 2014 10:31 am

Re: Hilfe bei Zeiger

Beitrag von patrickk83 » So Jan 12, 2014 12:08 pm

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

patrickk83
Beiträge: 4
Registriert: So Jan 12, 2014 10:31 am

Re: Hilfe bei Zeiger

Beitrag von patrickk83 » So Jan 12, 2014 12:11 pm

@Xin: Warum muß (void *) p bei printf angegeben werden?

Code: Alles auswählen

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

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Hilfe bei Zeiger

Beitrag von cloidnerux » So Jan 12, 2014 12:50 pm

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.
Redundanz macht wiederholen unnötig.
quod erat expectandum

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

Re: Hilfe bei Zeiger

Beitrag von Xin » So Jan 12, 2014 1:08 pm

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

patrickk83
Beiträge: 4
Registriert: So Jan 12, 2014 10:31 am

Re: Hilfe bei Zeiger

Beitrag von patrickk83 » So Jan 12, 2014 1:21 pm

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

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

Re: Hilfe bei Zeiger

Beitrag von Xin » So Jan 12, 2014 1:24 pm

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

Antworten