nach *Buffer++ - wie wieder zurück?

OP #2700682
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.
Gast #2700694
>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);
Gast #2700723
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.
#2700727
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?
OP #2700730
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 ;)
#2700744
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.
#2700947
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;

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.