Forum: Mikrocontroller und Digitale Elektronik nach *Buffer++ - wie wieder zurück?


von Oliver L. (ollil)


Lesenswert?

Moin,

irgendwie habe ich gerade n Brett vorm Kopf.

Folgender Code:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <sys/types.h>
4
5
int test(uint8_t *Buffer, uint16_t Bytes)
6
{
7
        uint16_t a;
8
        for ( a = 0; a < Bytes; a++ ) {
9
                *Buffer++ = 0x01;
10
        }
11
        *Buffer = *Buffer-512;
12
        printf("%x\n",Buffer[0]);
13
}
14
15
int main()
16
{
17
        uint8_t Buffer[512];
18
        uint16_t Bytes = 512;
19
20
        test(Buffer,Bytes);
21
        printf("%x\n",Buffer[0]);
22
}

Ausgabe:
gcc -o test7 test7.c && ./test7
d0
1

wie komme ich in test() wieder auf das 1. Byte von Buffer? Buffer steht 
ja nach dem loop 512 Bytes weiter - ich will ihn wieder auf den Anfang 
zuruecksetzen, da ich einiges noch machen will. Ich will innerhalb des 
for-loops nicht mit Buffer[a] arbeiten, da dies langsamer ist.

von Peter II (Gast)


Lesenswert?

>  *Buffer = *Buffer-512;

Buffer = Buffer-Bytes;

von Noname (Gast)


Lesenswert?

>wie komme ich in test() wieder auf das 1. Byte von Buffer?

Speichere Dir den Zeiger erstmal irgendwo zwischen.
1
uint8_t * Tmp = Buffer;

Dann kannst Du ihn später in dem printf verwenden.
1
printf("%x\n", Tmp);

von Lukas (Gast)


Lesenswert?

Was sollte denn in dieser Zeile passieren?
1
*Buffer++ = 0x01;

Ich sehs grad echt nicht!

von Fabian (Gast)


Lesenswert?

int test(uint8_t *Buffer, uint16_t Bytes)
{
        uint16_t a;
        for ( a = 0; a < Bytes; a++ ) {
                Buffer[a] = 0x01;
        }
        printf("%x\n",Buffer[0]);
}

von Peter II (Gast)


Lesenswert?

Fabian schrieb:
> int test(uint8_t *Buffer, uint16_t Bytes)
> {
>         uint16_t a;
>         for ( a = 0; a < Bytes; a++ ) {
>                 Buffer[a] = 0x01;
>         }
>         printf("%x\n",Buffer[0]);
> }

genauso wollte er es NICHT machen.

von Fabian (Gast)


Lesenswert?

Oh sorry, überlesen. ;-)
Aber ist es wirklich langsamer?! - Sollte der Optimierungsprozess des 
Compilers dies nicht in den Griff bekommen?
Soll es wirklich schnell gehen und der Compiler das nicht regeln, würde 
ich es einfach als Inline-Asm implementieren.

von Peter II (Gast)


Lesenswert?

Fabian schrieb:
> Oh sorry, überlesen. ;-)
> Aber ist es wirklich langsamer?!

auf einem PC nicht, auf einem kleinen Atmel kann das druchaus sein, weil 
er keine dazu passenden upcodes kennt.

von Karl H. (kbuchegg)


Lesenswert?

Oliver Lehmann schrieb:

> wie komme ich in test() wieder auf das 1. Byte von Buffer?

Wenn du eine Pointer-Variable hast, dann benennst du durch die 
Verwendung des Variablen-Namens alleine immer die Adresse auf die dieser 
Pointer zeigt.

    Buffer = Buffer + 2;

setzt also die Adresse um 2 Einheiten weiter. Der Zeiger zeigt danach 
auf eine andere Stelle im Speicher.

Setzt du VOR den Namen der Pointer-Variablen einen *, dann bedeutet das 
'Dereferenzieren'. D.h. gemeint ist dann nicht die Adresse, die in der 
Pointer Variablen gespeichert ist, sondern der Wert, der im Speicher 
unter dieser Adresse zu finden ist.


Graphisch veranschaulicht. Eine Pointer Variable zeige im Speicher auf 
eine Speicherzelle, in der der Wert 5 abgelegt sei

                            +---+
   Buffer                   | 3 |
   +--------+               +---+
   |   o------------------->| 5 |
   +--------+               +---+
                            | 9 |
                            +---+

'Buffer' alleine, wäre die Spezifikation für das Rechteck, über dem 
'Buffer' steht. Damit wird also die Variable manipuliert, an der der 
Pfeil seinen Ausgang nimmt. Tut man das, dann zeigt der Pfeil danach 
woanders hin.

   Buffer = Buffer + 1;

ist also die Anweisung, Buffer auf das nächste Element im Speicher 
zeigen zu lassen

                            +---+
   Buffer                   | 3 |
   +--------+               +---+
   |   o-----------+        | 5 |
   +--------+      |        +---+
                   +------->| 9 |
                            +---+


'*Buffer' hingegen ist die Spezifikation, das man sich auf das Ende des 
Pfeiles beziehen möchte. In diesem Fall eben die 5. Mittels *Buffer = 8; 
schreibt man also an die Stelle, auf die Buffer zeigt (ausgedrückt durch 
den *) eine 8

                            +---+
   Buffer                   | 3 |
   +--------+               +---+
   |   o------------------->| 8 |
   +--------+               +---+
                            | 9 |
                            +---+

Und das ist eine vollkommen andere Operation.

Und jetzt überleg noch mal, was wohl
1
       *Buffer = *Buffer-512;
macht. Worauf bezieht sich dieses Statement? Auf den Zeiger selber, oder 
auf das worauf er zeigt? Wo sind Dereferenzieungs-Sterne und wo nicht? 
Wo wird daher der Pointer selbst manipuliert und wo das, worauf er 
zeigt? Und wie deckt sich das mit dem, was du eigentlich tun willst?

von Oliver L. (ollil)


Lesenswert?

Peter II schrieb:
>>  *Buffer = *Buffer-512;
>
> Buffer = Buffer-Bytes;

So funzt es! Herzlichen Dank....

und bzgl. Peter IIs Frage:
1
*Buffer++ = 0x01;

Schreibt an den Anfang des Zeiger Buffer den Wert 0x01.
Also equivalent zu Buffer[0] = 0x01;
Danach wird der Zeiger um 1 Byte erhöht, er zeigt dann also beim 
nächsten
Durchlauf der Schleife auf Buffer[1] - quasi.
0x01 ist hier nur ein Testwert zur Veranschalichung.

Und zummindest auf meinem ATMega mit gcc -O1 ist *Buffer++= schneller 
als Buffer[a]=. Nein, ich poste jetzt keinen ASM Code ;)

von Noname (Gast)


Lesenswert?

Karl Heinz mal wieder. Kriegst n Keks. :-)

von Oliver L. (ollil)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Und jetzt überleg noch mal, was wohl       *Buffer = *Buffer-512;
> macht. Worauf bezieht sich dieses Statement? Auf den Zeiger selber, oder
> auf das worauf er zeigt?

Wunderschöne Erklärung, danke!
es bezieht sich auf  das Ende des Pfeiles und rechnet dann wohl 0x01-512

von Karl H. (kbuchegg)


Lesenswert?

Oliver Lehmann schrieb:
> Karl Heinz Buchegger schrieb:
>
>> Und jetzt überleg noch mal, was wohl       *Buffer = *Buffer-512;
>> macht. Worauf bezieht sich dieses Statement? Auf den Zeiger selber, oder
>> auf das worauf er zeigt?
>
> Wunderschöne Erklärung, danke!

Das geile ist eigentlich:
Wenn du das kapiert und verinnerlicht hast, dann hast du Pointer 
verstanden. Alles weitere folgt daraus und ist eine direkte Konsequenz 
davon: Bei Pointern gibt es 2 Möglichkeiten der Operationen - entweder 
ich manipuliere die Adresse im Pointer selber oder ich manipuliere das 
worauf diese Adresse verweist. In C ist der Unterschied zwischen diesen 
beiden möglichen Operationen der '*' vor dem Variablennamen. Der wählt 
aus, welches Ende des PFeiles gemeint ist: der Anfang oder das Ende. 
Alle anderen Dinge sind nur syntaktische Variationen davon, die zwecks 
einfacherer Schreibweise eingeführt wurden.

von Marcus O. (marcus6100)


Lesenswert?

Karl Heinz Buchegger schrieb:

> *Buffer = *Buffer-512;

>>> macht. Worauf bezieht sich dieses Statement? Auf den Zeiger selber, oder
>>> auf das worauf er zeigt?
>>
>> Wunderschöne Erklärung, danke!
>
> Das geile ist eigentlich:

Ja super. Alles toll.

C operator precedence direkt mal nachlesen als nächstes.

Von mir jetzt noch der Hinweis, dass Buffer ein uint8_t array ist,
und es deshalb nicht sinnvoll ist, den wert 0x01 - 512 = -511 drin
speichern und rauslesen zu wollen.


> *Buffer = *Buffer-512;

von Oliver L. (ollil)


Lesenswert?

Marcus Overhagen schrieb:
> Von mir jetzt noch der Hinweis, dass Buffer ein uint8_t array ist,
> und es deshalb nicht sinnvoll ist, den wert 0x01 - 512 = -511 drin
> speichern und rauslesen zu wollen.
>
>
>> *Buffer = *Buffer-512;

Zum Glück hatte das auch keiner vor....

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.