Guten Tag, könnte mir jemand einen Tip geben, warum zwischen den folgenden beiden Code-Versionen für eine Ring-Puffer-Implementierung (dsPic30F6014, C30) ein Unterschied sein könnte: //defines und deklarierte Variablen .. #define rvmask 15 unsigned int rxbuf[rvmask+1]; unsigned char rxbufp=0; unsigend int rxr; .. //Code-Version 1: .. rxbufp = (rxbufp++)&rvmask; rxr = rxbuf[rxbufp]; .. //Code-Version 2: .. rxbufp++; rxbufp = rxbufp&rvmask; rxr = rxbuf[rxbufp]; .. Die zweite Code-Version funktioniert einwandfrei, während bei der ersten die Maskierung von rxbufp überhaupt nicht funktioniert und der Ring-Puffer-Indexierung fehlschlägt. rxbufp wird nicht wieder auf Null gebracht beim überschreiten von rvmask (erst beim char-overflow von 255->0 wird der Wert automatisch wieder Null). Wieso das? Hat jemand eine Idee. Vielen Dank. S. Leven
In Version 2 wird rxbufp zuerst incrementiert und dann mit rvmask verknüpft. Um das gleiche zu erzielen müsste Version 1 IMO so aussehen: rxbufp = (++rxbufp)&rvmask; rxr = rxbuf[rxbufp];
ist das nicht so, daß rxbuf selbst schon eine Adresse (pointer) ist? Bischen komisch finde ich... g. Vex
> ist das nicht so, daß rxbuf selbst schon eine Adresse (pointer) ist?
Wie kommst du da drauf?
unsigned int rxbuf[rvmask+1];
rxbuf ist eindeutig ein Array.
Ein Array ist kein Pointer!
Ein Array ist kein Pointer!
Ein Array ist kein Pointer!
Unter rxbufp würde ich einen Pointer (Adresse) vermuten, ist also irreführend. Einen Index sollte man rxbufi oder besser rxbuf_idx nennen. Peter
@Karl ähm .. ich hab da was anderes gelesen ein Array bzw. der Bezeichner ist in erster Linie eine Adresse eines Speicherberiches und jetzt sag mir mal was dann ein Pointer ist.. ich schreib das mal, was ich bei mir da stehen hab Pointer und Arrays Zwischen beiden besteht ein sehr enger Zusammenhang, der soweit geht, dass der Name eines Arrays selbst ohne Array-Index[i] schon ein Pointer vom Typ der Arrayelemenete ist.... (Quelle: C für Microcontroller B. Mann)
Übrigens steht da auch ein Beispiel zu den Puffer: int DataArray[8]; int *pInt; pInt = DataArray; //diese Zuweisung pInt = &DataArray[0]; //oder diese sind indentisch pInt += 1; //Zeigt auf das nächste Arrayelement identisch mit pInt++ pInt -= 1; //zeigt auf das vorherrige Element identsich mit pInt--
pInt ist in deinem Beispiel der Pointer: pInt ist ein Bezeichner für eine Speicheradresse, in dieser Speicheradresse steht die Adresse eines Elements von DataArray.
jau war mir schon klar wie das geht .. bin nur bei Source oben nicht ganz schlau draus geworden und wie es schon Peter sagte mit den Pointer Bezeichnern da drin kann man das schon etwas missverstehen, was nun ein Pointer und was die eigentliche Speicherstelle ist Vex
> Karl ähm .. ich hab da was anderes gelesen ein Array bzw. der > Bezeichner ist in erster Linie eine Adresse eines Speicherberiches > und jetzt sag mir mal was dann ein Pointer ist.. Wenn das dort tatsächlich so gestanden hat, dann verbrenne sofort die Quelle (das Buch) und grab die Asche 3 Meter tief ein. Das ist eine der größten Falschinformationen über C. Ein Array ist kein Pointer! Ein Array ist ein Speicherbereich in dem Werte gespeichert werden. Die Sammlung all dieser Werte ist unter dem Namen des Arrays bekannt. Ein Pointer seinerseits ist eine ganz normale Variable, die eine Speicheradresse beinhaltet. Teil der Konfusion ist sicherlich die übliche Vorgehensweise den Terminus 'Pointer' für 2 verschiedene Dinge zu verwenden: * Für eine Variable, die eine Speicher-Adresse enthält * Für die Speicher-Adresse selbst. Wie ist es wirklich: Wird der Name eines Arrays alleine verwendet (also ohne einen Indizierungsausdruck), so degeneriert der Name des Arrays zur ersten Speicheradresse des ersten Array-Elements. (Da fängts schon an: Ich habe bewusst 'erste Speicheradresse geschrieben. Übliche Ausdrucksweise ist: ... degeneriert zu einem Pointer auf das erste Array-Element). Wichtig: Das ganze ist immer noch ein Array und kein Pointer! Nur weil etwas wie ein Pointer benutzt wird, heist es nicht das das ein Pointer ist! Wenn du also hast: int Tmp[5]; dann degeneriert der Ausdruck 'Tmp' alleine in den meisten Fällen (eine Ausnahme wäre zb. sizeof) zu einem Pointer auf das erste Element von Tmp. So zb in foo( Tmp ); Hier degeneriert Tmp zu einem Pointer auf Tmp[0]. Man könnte auch salopp sagen, dass 'Tmp' synonym ist zu '&Tmp[0]' Ein interessanter Punkt in C ist die Art und Weise wie Array-Zugriffe überhaupt definiert sind. In C ist Array- Indizierung eine ganz banale Sache. Es ist definiert, dass der Compiler einen Ausdruck der Form: a[b] sofort in die Form *(a+b) umformen muss. d.h. hier kommt wieder der Name des Arrays alleine vor (a) und daher degeneriet dieser Ausdruck sofort zu ersten Speicheradresse des Arrays. b ist der Index und wie immer bei Pointer-Arithmetik wird dbei Addition eines Integer-Typen zu einem Pointer, der Integer-Typ zuerst mit dem sizeof des Pointer-Quelltyps multipliziert. Obiges ist daher equivalent zu: *( ((unsigned char*)a) + b * sizeof( *a ) ) Diese Transformation macht der Compiler intern, wenn er auf einen Ausdruck a[b] stoesst. Interessant, aber völlig logisch, ist daher, dass man auch schreiben kann int a[5]; int b; b[a] Der Compiler muss das akzeptieren, da ja dieser Ausdruck equivalent zu *(b + a) ist und Addition kummutativ ist. b + a ist dasselbe wie a + b Und ob ich jetzt zu einem Pointer einen Integer hinzuzähle oder zu einem Integer einen Pointer spielt keine Rolle. Ein Fall an dem es ganz besonders ins Auge geht, dass ein Array eben kein Pointer ist, ist folgender: In einer C-Einheit vereinbart man eine globale Variable int Array[5]; und in einer anderen C-Einheit versucht man Zugang zu dieser globalen Variable zuerhalten: extern int* Array; Das kann so nicht gut gehen. Denn wie gesagt: Ein Array ist kein Pointer. Im ersten Fall bezeichnet der Name Array einen Speicherbereich an dem die tatsächlichen int-Werte zu finden sind. Im zweiten Fall aber wird deklariert, dass Array der Name eines Speicherbereiches ist, in dem die tatsächliche Speicheradresse zu finden ist, an dem die int abeleget sind. In graphischer Form (und irgendwelche Werte für die int angenommen) Array +----+----+----+----+----+ | 0 | 20 | 30 | 40 | 10 | +----+----+----+----+----+ versus Array +------+ +----+----+----+----+----+ | o------------------->| 0 | 20 | 30 | 40 | 10 | +------+ +----+----+----+----+----+ man sieht recht deutlich, dass das 2 vollkommen verschiedene Dinge sind, auch wenn beide Varianten (und dass ist das perverse daran) mit vollkommen identischer Syntax beim Zugriff benutzt werden. Die richtige Schreibweise wäre im 2-ten Fall extern int Array[]; und das ist (wie bereits gezeigt) was völlig anderes als extern int* Array; Klarer?
... wie ich sehe, ist Karl Heinz schon etwas über "Hallo Welt" hinaus ;-). Sauber erklärt!
Ja Danke echt gut erklärt Karl! aber ich wollte auch nie sagen, daß ein Array ein Pointer ist sondern andeuten, daß ein Array Bezeichner genau wie ein Pointer lediglich eine Adresse (nat. wenn der Pointer eine zugewiesen bekommen hat) darstellt .. und mehr nicht. Genau aus dem Grund - weil ein Array kein Pointer ist, würde ich z.B. einer Funktions nicht ein Array , sondern den Pointer auf dieses übergeben .. klar oder? Gruss Vex
da Fällt mir noch was ein.. ich hatte mal Probs mit diesen Code: char myarray[8]; int tuwas(int *p_array); und wenn ich jetzt die Funktion aufrufe mit tuwas(&myarray) .. rate mal was dann passiert?
Klar
Dann habe ich Deine Aussage
> ist das nicht so, daß rxbuf selbst schon eine Adresse (pointer) ist?
falsch interpretiert.
Sorry dafür.
Es ist nur so, dass diese Thematik eine der grossen
Stolpersteine für alle C-Einsteiger ist. Daher reagiere
ich ein klein wenig allergisch, wenn im selbsen Satz die
Wörter 'Array', 'Pointer' und 'ist' vorkommen.
"rxbufp = (rxbufp++)&rvmask;" "rxbufp = (++rxbufp)&rvmask;" Ist beides undefiniert, weil hier effektiv zwei Zuweisungen an rxbufp enthalten sind ("=" und "++"), und mangels sequence point nicht definiert ist, welche zuerst erfolgt. "=" ist kein sequence point.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.