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