Hallo, ich habe aus einer Library eine globale Variable cDevStatus (unsigned char). Ich mmöchte nun gerne auf diese über eine Bit Struktur zugreifen. Meine Idee ist recht simple, leider bekomme ich sie nicht zum Laufen. struct sDevStatus { unsigned char Stat0 :1; unsigned char Stat1 :1; . . unsigned char Stat7 :1; }; union uDevStatus { struct sDevStatus sDevStatus; unsigned char *pDevStatus; }; union uDevStatus uDevStatus; uDevStatus.pDevStatus = & cDevStatus; Jetzt müßte ich doch über meine Structur direkt auf die globale Variable cDevStatus schreiben, z.B: uDevStatus.sDevStatus.Stat0 = 1; Leider sehe ich beim Debuggen nicht das die 1 dann auch in cDevStatus steht. Kann mir vielleicht jemand meinen Denkfehler aufdecken. Vielen Dank, Sebastian
> union uDevStatus > { > struct sDevStatus sDevStatus; > unsigned char *pDevStatus; > }; Hier überlagerst du deine Bitstruktur mit einem Pointer. D.h. deine Bitstruktur spiegelt (zum Teil) die Bits des Pointers wieder und nicht der Variablen, auf die der Pointer zeigt. Dein Problem ist gar nicht so einfach zu lösen. So rum müsste es aber gehen. Du installierst dir einen Pointer auf so eine BitStruktur: struct sDevStatus* pDevStatus; und jetzt sorgst du dafür, dass der Pointer auf das eine Byte zeigt, dass dich interessiert: pDevStatus = ( struct sDevStatus* ) & cDevStatus; Jetzt kannst du über pDevStatus auf das Byte zugreifen. pDevStatus->Stat0 = 1; Der Trick liegt ganz einfach im Umcasten des Datentyps. Man könnte daher den Pointer auch komplett einsparen, indem man schreibt: ((struct sDevStatus)cDevStatus).Stat0 = 1; Da das ein bischen länglich ist, würde ich mir erst mal dafür ein Makro bauen: #define DEV_STATUS ((struct sDevStatus)cDevStatus) damit kann man das dann etwas schöner formulieren: DEV_STATUS.Stat0 = 1;
Super, erscheint mir absolut logisch. Werde ich nachher gleich mal ausprobieren. --Hier überlagerst du deine Bitstruktur mit einem Pointer. --D.h. deine Bitstruktur spiegelt (zum Teil) die Bits des --Pointers wieder und nicht der Variablen, auf die der Pointer --zeigt. Naja, also eigentlich dachte ich, das ich den pointer auf den Anfang der Bitstruktur zeigen lasse. Also nicht überlagern. Bzw. den Pointer so ausrichte das er auf die Adresse der globalen Variable zeigt. Somit müßte doch die Bitstruktur genau über der globalen Variablen liegen. Oder? Sebastian
Das möchtest du vielleicht machen. Aber das hier > union uDevStatus > { > struct sDevStatus sDevStatus; > unsigned char *pDevStatus; > }; macht ganz was anderes. Eine union benutzt für alle seine Member den gleichen Speicher. Damit liegen sDevStatus und pDevStatus an der selben Speicheradresse. Wohin der Pointer zeigt ist den sDevStatus völlig Wurscht. sDevStatus spiegelt den Inhalt des Pointers wieder, nicht worauf der Pointer zeigt.
Ok ich hab's kapiert. Die Variante mit dem pointer funktioniert ausgezeichnet :-). Die Variante mit dem Typcast, allerdings nicht. ((struct sDevStatus)cDevStatus).Stat0 = 1; // Fehler "Type Cast": char kann nicht in struct sDevStatus konvertiert werden. // Fehler Der linke Teil muss eine Klasse/Struktur/Union sein. Wäre tool wenn diese Variant auch noch funktionieren würde. Vielen, vielen Dank, Sebastian
> (*((struct sDevStatus *) (void) &cDevStatus)).Stat0 = 1; :-) (*((struct sDevStatus *) (void *) &cDevStatus)).Stat0 = 1; ^ | Keine Angst, sieht nur kompliziert aus. Der Compiler sollte das eigentlich ordentlich wegoptimieren. > ((struct sDevStatus)cDevStatus).Stat0 = 1; > // Fehler "Type Cast": char kann nicht in struct sDevStatus > konvertiert werden. > // Fehler Der linke Teil muss eine Klasse/Struktur/Union sein. Sorry. Habs vorher nicht ausprobiert. Ich hätte allerdings schwören können, dass ein C-Compiler das anstandslos akzeptiert. Mein C ist allerdings nach 10 Jahren C++ etwas rostig und ich bin nicht mehr auf der Höhe der Zeit was Veränderungen im C-Standard angeht.
(*((struct sDevStatus *) (char) &cDevStatus)).Stat0 = 1; Das obige Konstrukt kann zwar kompiliert werden allerding erhalte ich immer Access violations. Den obigen Typcast muss ich mir mal am WE in Ruhe anschauen. Mit der Pointer-Variante bin ich momentan absolut glücklich :-). Sebastian
Wie bist du denn auf die Idee gekommen, den Zeiger in einen char zu konvertieren? Dadurch wird er zerstückelt.
> (*((struct sDevStatus *) (char) &cDevStatus)).Stat0 = 1; > > Das obige Konstrukt kann zwar kompiliert werden allerding erhalte > ich immer Access violations. Das wundert mich nicht. Zerlegen wir mal: cDevStatus Variable cDevStatus &cDevStatus davon die Adresse (16 Bit) (char)&cDevStatus das ganze gecastet nach char. Da haben wir aber ein Problem: Eine Adresse hat 16 Bit, ein char nur 8 Bit. Also muss irgendwas verloren gehen! (...) Der Rest ist nur noch Makulatur. Dadurch, dass die Adresse von 16 Bit auf 8 Bit gekürzt wurde, ist alles andere sinnlos. Casts sind Waffen!
Mist ich hatte das Sternchen bei void vergessen. Dann habe ich einfach mal schnell ein char eingefügt und schon "kam der Compiler" durch. Mit bekannten runtime folgen. Mit (void *) funktioniert das alles perfekt. Also was lernt man draus. Erst kapieren dann probieren ;-). An alle, Merci.
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.