Hallo Freaks,
ich bin noch ein C++ Anfänger und möchte aus einer Datei einzelne Bits
auslesen können ... leider finde ich nur die Möglichkeit Chars
auszulesen ...
Hoffentlich kann mir jemand einen Tipp geben wie man einzelne Bits
auslesen kann ... oder ist es wirklich die einzige möglichkeit ein
C-String auszulesen und dann in diesem die einzelnen Bits zu untersuchen
...
tia
OLI
--
Tim Oliver Wagner
Am Freitag, 16. Mai 2003 15:55 schrieb Tim Oliver Wagner:
ich bin noch ein C++ Anfänger und möchte aus einer Datei einzelne Bits auslesen können ... leider finde ich nur die Möglichkeit Chars auszulesen ...
Das Byte ist traditionell die kleinste adressierbare Einheit in der EDV.
Hoffentlich kann mir jemand einen Tipp geben wie man einzelne Bits auslesen kann ... oder ist es wirklich die einzige möglichkeit ein C-String auszulesen und dann in diesem die einzelnen Bits zu untersuchen ...
Wirst nicht drum rumkommen. -- Machs gut | http://www.iivs.de/schwinde/buerger/tremmel/ | http://packman.links2linux.de/ Manfred | http://www.knightsoft-net.de
Hi all, Am Friday 16 May 2003 17:20 schrieb Manfred Tremmel:
Am Freitag, 16. Mai 2003 15:55 schrieb Tim Oliver Wagner:
ich bin noch ein C++ Anfänger und möchte aus einer Datei einzelne Bits auslesen können ... leider finde ich nur die Möglichkeit Chars auszulesen ...
Ist auch so ;)
Das Byte ist traditionell die kleinste adressierbare Einheit in der EDV.
Adressierbar schon, aber es gibt ja noch Bitfelder(C) und bitsets in C++.
Hoffentlich kann mir jemand einen Tipp geben wie man einzelne Bits auslesen kann ... oder ist es wirklich die einzige möglichkeit ein C-String auszulesen und dann in diesem die einzelnen Bits zu untersuchen ...
Wirst nicht drum rumkommen.
Du kannst byte für byte die Datei auslesen und jedes Byte (oder mehr) in bitfelder packen. /* C */ typedef struct { char bit0 : 1; char bit1 : 1; char bit2 : 1; char bit3 : 1; char bit4 : 1; char bit5 : 1; char bit6 : 1; char bit7 : 1; } t_Bit; typedef union { char base; BitTyp field; } t_BitUnion; for (i=0; i < sizeof(c_array); i++) { t_BitUnion.base = c_array[i]; // Bit '0' ausgeben printf("%d ", t_BitUnion.field.bit0 ); } // C++ #include <bitsets> // siehe STL c++ char c; int pos = 1; bitsets<8> bs(c); if (bs.test(pos)) { // test(size_t pos) gibt ein bool zurück machwas(); } Vielleicht hilft das weiter ... Bye Andre
Hi
Hoffentlich kann mir jemand einen Tipp geben wie man einzelne Bits auslesen kann ... oder ist es wirklich die einzige möglichkeit ein C-String auszulesen und dann in diesem die einzelnen Bits zu untersuchen ...
Wirst nicht drum rumkommen.
Du kannst byte für byte die Datei auslesen und jedes Byte (oder mehr) in bitfelder packen.
Vielleicht kann man auch am anderen Ende ansetzen. Mir faellt spontan nichts ein, was als einzelne Bits in einer Datei gespeichert ist. Allenfalls eine Eigenloesung. Vielleicht laesst sich das Problem loesen, indem der, der bisher Bits schreibt, zukuenftig Bytes schreibt? So gross ist der Aufwand die einzelnen Bits aus einem Byte zu ziehen auch nicht. Dann wird das Programm halt zwei Zeilen laenger. Bye -- 1 Bodo Kaelberer 123 http://www.webkind.de/ 3 4 "A button I have made must be pushed." (ip)
Hi, Am Friday 16 May 2003 19:40 schrieb Bodo Kaelberer:
Hoffentlich kann mir jemand einen Tipp geben wie man einzelne Bits auslesen kann ... oder ist es wirklich die einzige möglichkeit ein C-String auszulesen und dann in diesem die einzelnen Bits zu untersuchen ...
[...]
Vielleicht kann man auch am anderen Ende ansetzen. Mir faellt spontan nichts ein, was als einzelne Bits in einer Datei gespeichert ist. Allenfalls eine Eigenloesung. Vielleicht laesst sich das Problem loesen, indem der, der bisher Bits schreibt, zukuenftig Bytes schreibt?
Hmm, da könntest Du natürlich richtig liegen :)
So gross ist der Aufwand die einzelnen Bits aus einem Byte zu ziehen auch nicht. Dann wird das Programm halt zwei Zeilen laenger.
ACK Geht auch alles ohne bitfelder, char test = 'A'; if ((test & 0x1)) { /* Bit 0 ist gesetzt... */ } Da sind wohl die Bitoperatoren die beste Wahl ... Ciao andre
Am Fre, 2003-05-16 um 20.42 schrieb Andre Heine:
Hi,
Am Friday 16 May 2003 19:40 schrieb Bodo Kaelberer:
Hoffentlich kann mir jemand einen Tipp geben wie man einzelne Bits auslesen kann ... oder ist es wirklich die einzige möglichkeit ein C-String auszulesen und dann in diesem die einzelnen Bits zu untersuchen ...
[...]
Vielen Dank schon mal für Eure Tipps
Vielleicht kann man auch am anderen Ende ansetzen. Mir faellt spontan nichts ein, was als einzelne Bits in einer Datei gespeichert ist. Allenfalls eine Eigenloesung. Vielleicht laesst sich das Problem loesen, indem der, der bisher Bits schreibt, zukuenftig Bytes schreibt?
Hmm, da könntest Du natürlich richtig liegen :)
Es geht hier um video-Dateien ... also um einen Video decoder ... da
braucht man den BIT-Stream ... wäre nicht besonders vorteilhaft, wenn
das Video-File 8 mal so groß wird ... ;-) ... abgesehen davon muss ich
mich ja an den Standard halten und der will es halt bitweise ...
Grüße
OLI
--
Tim Oliver Wagner
Am Sam, 2003-05-17 um 09.25 schrieb Tim Oliver Wagner:
Am Fre, 2003-05-16 um 20.42 schrieb Andre Heine:
Hi,
Am Friday 16 May 2003 19:40 schrieb Bodo Kaelberer:
Hoffentlich kann mir jemand einen Tipp geben wie man einzelne Bits auslesen kann ... oder ist es wirklich die einzige möglichkeit ein C-String auszulesen und dann in diesem die einzelnen Bits zu untersuchen ...
[...]
Vielen Dank schon mal für Eure Tipps
Vielleicht kann man auch am anderen Ende ansetzen. Mir faellt spontan nichts ein, was als einzelne Bits in einer Datei gespeichert ist. Allenfalls eine Eigenloesung. Vielleicht laesst sich das Problem loesen, indem der, der bisher Bits schreibt, zukuenftig Bytes schreibt?
Hmm, da könntest Du natürlich richtig liegen :)
Es geht hier um video-Dateien ... also um einen Video decoder ... da braucht man den BIT-Stream ... wäre nicht besonders vorteilhaft, wenn das Video-File 8 mal so groß wird ... ;-) ... abgesehen davon muss ich mich ja an den Standard halten und der will es halt bitweise ...
Es ist nirgends, auf keiner Hardware, mit keinem Compiler/Assembler, auf keinem Betriebssystem möglich, etwas, was kleiner ist als ein Byte zu lesen/schreiben. Alles was Du tun kannst, ist Bits innerhalb von Bytes ausmaskieren (C-Bitfeld und C++-std::bitfield Operatoren machen auch nichts anderes). Ralf
Hallo
Es geht hier um video-Dateien ... also um einen Video decoder ... da braucht man den BIT-Stream ... wäre nicht besonders vorteilhaft, wenn das Video-File 8 mal so groß wird ... ;-) ... abgesehen davon muss ich mich ja an den Standard halten und der will es halt bitweise ...
Das ist ja ein nettes Thema fuer Einsteiger (-; Wie gelesen: Bytes sind die kleinste Einheit. Es gab auch glaub schon Loesungsvorschlaege, wie Du aus den Bytes Bits machen kannst. Mein Vorschlag noch dazu (vielleicht gab es den auch schon): ================================================================= #include <iostream> using namespace std; bool byteToBit( unsigned char value, unsigned char &result ) { static unsigned char andFlag = 0x01; result = ( value & andFlag ) != 0 ? 0x01 : 0x00; andFlag = andFlag << 1; if ( andFlag == 0 ) { // Eine ganze Runde (8 shifts) gemacht? andFlag = 0x01; return true; // true = neues Byte noetig } else { return false; // false = Weiter mit altem Byte } } int main() { unsigned char data[] = { 0x01, 0xF0, 0x34 }; // Dummy-Data unsigned char currentByte; unsigned char currentBit; bool needNewByte; for ( int i = 0; i < 3; i++ ) { currentByte = data[i]; // Neues Byte holen. !!File-In!! do { needNewByte = byteToBit( currentByte, currentBit ); if ( currentBit ) cout << "1"; else cout << "0"; } while ( !needNewByte ); cout << " "; } } =============================================================== Die Funktion byteToBit() beginnt beim niedrigsten Bit. Willst Du mit dem hoechsten beginnen, dann muss Du als Anfangswert 0x80 statt 0x01 verwenden und zum Schiften >> statt <<. Ausgabe: 10000000 00001111 00101100 Das ist vom Aufruf her recht komfortabel. Es wirkt etwas umstaendlich, aber dafuer hat es ein stream-artiges Verhalten - Du kannst wirklich Bit fuer Bit lesen. Die Performance kann ich nicht abschaetzen. Bye -- 1 Bodo Kaelberer 123 http://www.webkind.de/ 3 4 "A button I have made must be pushed." (ip)
Am Saturday 17 May 2003 14:35 schrieb Bodo Kaelberer: [...]
Das ist ja ein nettes Thema fuer Einsteiger (-;
Jep :)
Die Funktion byteToBit() beginnt beim niedrigsten Bit. Willst Du mit dem hoechsten beginnen, dann muss Du als Anfangswert 0x80 statt 0x01 verwenden und zum Schiften >> statt <<.
Ausgabe: 10000000 00001111 00101100
Das ist vom Aufruf her recht komfortabel. Es wirkt etwas umstaendlich, aber dafuer hat es ein stream-artiges Verhalten - Du kannst wirklich Bit fuer Bit lesen. Die Performance kann ich nicht abschaetzen.
Im C Buch von Suse Press steht, das Bitfelder langsamer sind, weil diese intern "shiften", bit Verknüpfungen(& |) sollen sehr performant sein, aber nicht speicherefffizient wie Bitfelder... Meine Vorliebe liegt bei den Bitfeldern, lässt sich im Quelltext viel besser lesen. Die Geschwindigkeit ist für meine User-Space Programme nicht wirklich von Bedeutung, meist muss ich Timer zum 'bremsen' setzen. Die C Variante mag ich am liebsten, weil man die Union super in verschiedene Ranges aufteilen kann und ist sehr übersichtlich in den Quellen! Ciao Andre
Am Sam, 2003-05-17 um 16.23 schrieb Andre Heine:
Am Saturday 17 May 2003 14:35 schrieb Bodo Kaelberer:
[...]
Das ist ja ein nettes Thema fuer Einsteiger (-;
Jep :)
Die Funktion byteToBit() beginnt beim niedrigsten Bit. Willst Du mit dem hoechsten beginnen, dann muss Du als Anfangswert 0x80 statt 0x01 verwenden und zum Schiften >> statt <<.
Ausgabe: 10000000 00001111 00101100
Das ist vom Aufruf her recht komfortabel. Es wirkt etwas umstaendlich, aber dafuer hat es ein stream-artiges Verhalten - Du kannst wirklich Bit fuer Bit lesen. Die Performance kann ich nicht abschaetzen.
Im C Buch von Suse Press steht, das Bitfelder langsamer sind, weil diese intern "shiften", bit Verknüpfungen(& |) sollen sehr performant sein, aber nicht speicherefffizient wie Bitfelder... So pauschal ausgedrückt, ist diese Aussage falsch.
Die Effizienz von C-Bitfeldern ist sehr compiler- und prozessorabhängig. Das Ergebnis kann je nach Anwendung, Compiler und Prozessor sehr unterschiedlich ausfallen. "Verknüpfungen" (Bit-Operationen) sind insbes. dann signifikanter effizienter, wenn der Autor eines Programmes "Shifts" vermeidet, in dem er Bits in Ordinaltypen direkt setzt und Vergleiche mit den Ordinaltypen selbst (Bit-Masken) verwendet, statt einzelne Bits zu setzen bzw. einzelne Bits zu vergleichen.
Meine Vorliebe liegt bei den Bitfeldern, lässt sich im Quelltext viel besser lesen. Grösster Nachteil von C-Bitfeldern: Die interne Reihenfolge der Bits innerhalb von structs ist nicht definiert.
D.h. so bald C-Bitfelder binär ausgegeben werden sollen oder Hardware mit Bitfeldern angesteuert werden sollen, wird der Code unportabel. Ralf
Hi Ralf,
From: "Ralf Corsepius"
Am Sam, 2003-05-17 um 16.23 schrieb Andre Heine: [...]
Im C Buch von Suse Press steht, das Bitfelder langsamer sind, weil diese intern "shiften", bit Verknüpfungen(& |) sollen sehr performant sein, aber nicht speicherefffizient wie Bitfelder... So pauschal ausgedrückt, ist diese Aussage falsch. Die Effizienz von C-Bitfeldern ist sehr compiler- und prozessorabhängig. Das Ergebnis kann je nach Anwendung, Compiler und Prozessor sehr unterschiedlich ausfallen.
Das stimmt, Bits können je nach Prozessor/ Compiler anders angeordnet sein. Aber wenn ich ein Bitfeld habe, wo ich "union.bittyp.bit0 = 1" setze, muss das ist immer so sein! Ich meine, es ist egal das der Compiler das nun rechts oder links anordnet. bit0 im struct ist immer '1'. In meinen Beispiel benutze ich in einer "union" eine "unsigned char" mit einem Bitfeld, d.h, wenn nun der Compiler die Bits anders für das "unsigned char" anordnet, ist das natürlich fatal, weil eben die Reihenfolge anders ist. Das wird ein BUG im Programm, den ich nicht gerne suchen möchte :))) ( Wer denkt sofort an die Bitausrichtung, na gut Ralf schon *Grins* ) [...]
Meine Vorliebe liegt bei den Bitfeldern, lässt sich im Quelltext viel besser lesen. Grösster Nachteil von C-Bitfeldern: Die interne Reihenfolge der Bits innerhalb von structs ist nicht definiert. D.h. so bald C-Bitfelder binär ausgegeben werden sollen oder Hardware mit Bitfeldern angesteuert werden sollen, wird der Code unportabel.
Das habe ich, ehrlich gesagt, gar nicht bedacht... Da brauche ich eigentlich nur die vorhandenen Bitfelder "umdrehen" und schon sollte mein Code immernoch lesbar sein und auch dieses manko beheben. Mit defines kann man das ja Konfigurieren, welche bitfelder genommen werden, je nach Prozessor ... Ciao andre
Am Mon, 2003-05-19 um 11.41 schrieb Andre Heine:
Hi Ralf,
From: "Ralf Corsepius"
Am Sam, 2003-05-17 um 16.23 schrieb Andre Heine: [...]
Im C Buch von Suse Press steht, das Bitfelder langsamer sind, weil diese intern "shiften", bit Verknüpfungen(& |) sollen sehr performant sein, aber nicht speicherefffizient wie Bitfelder... So pauschal ausgedrückt, ist diese Aussage falsch. Die Effizienz von C-Bitfeldern ist sehr compiler- und prozessorabhängig. Das Ergebnis kann je nach Anwendung, Compiler und Prozessor sehr unterschiedlich ausfallen.
Das stimmt, Bits können je nach Prozessor/ Compiler anders angeordnet sein.
Darauf bezog ich mich an dieser Stelle gar nicht. Was ich meinte, ist folgendes: Was ist scheller und portabler? a) "Bitfeld-Char": struct { unsigned char c0:1; unsigned char c1:1; } b; .. b.c0 = 1; b.c1 = 1; ... if ( (b.c0 == 1) || (b.c1 == 1) ) /* tu was */ .. .. b.c1 = 1; .. oder b) "Bit-Masken/Char" char c ; ... c = 0x03; if ( c & 0x03 ) /* tu was */ .. c |= 0x02 ; b) ist in der Regel erheblich schneller, da mehrere Bits gleichzeitig verarbeitet werden, dafür aber unübersichtlicher. Wertet man in seinem Code aber nur einzelne Bits aus, geht dieser Vorteil von b) verloren, In diesem Fall kann der Compiler zur Verarbeitung der Bitfelder dann u.U. spezialisierten Code erzeugen, der den einfachen "Bit-Ops" des Bit-Masken-Ansatzes überlegen und schneller sein kann.
Aber wenn ich ein Bitfeld habe, wo ich "union.bittyp.bit0 = 1" setze, muss das ist immer so sein!
Ich meine, es ist egal das der Compiler das nun rechts oder links anordnet. bit0 im struct ist immer '1'. Jein, solange Du diese Struct nur als interne Datenstruktur verwendest spielt es keine Rolle. Sobald aber I/O ins Spiel kommt, sieht die Sache anders aus.
In meinen Beispiel benutze ich in einer "union" eine "unsigned char" mit einem Bitfeld, d.h, wenn nun der Compiler die Bits anders für das "unsigned char" anordnet, ist das natürlich fatal, weil eben die Reihenfolge anders ist.
Das wird ein BUG im Programm, den ich nicht gerne suchen möchte :)) ;) Ja, soetwas ist teuflisch zu suchen.
( Wer denkt sofort an die Bitausrichtung, na gut Ralf schon *Grins* ) Ach, diesen Diesen Punkt erreicht man schnell, wenn man sich mal mit Hardware-naher Programmierung oder mit Kommunikation zwischen verschiedenen OSen und/oder Architekturen beschäfftigt. -- Ich bin in beiden Feldern zu Hause.
Man lernt dann schnell scheinbar elegante Tricks ähnliche diesem hier zu vermeiden: union { unsigned int i; struct { unsigned char pad0:7; unsigned char c7:1; unsigned char c8:1; unsigned char pad:5; unsigned char c13:1; unsigned char ; unsigned char c20:1; } u; } mytype ; Frage: An welchem Bit in i steht c13? SCNR :-)
[...]
Meine Vorliebe liegt bei den Bitfeldern, lässt sich im Quelltext viel besser lesen. Grösster Nachteil von C-Bitfeldern: Die interne Reihenfolge der Bits innerhalb von structs ist nicht definiert. D.h. so bald C-Bitfelder binär ausgegeben werden sollen oder Hardware mit Bitfeldern angesteuert werden sollen, wird der Code unportabel.
Das habe ich, ehrlich gesagt, gar nicht bedacht...
Da brauche ich eigentlich nur die vorhandenen Bitfelder "umdrehen" und schon sollte mein Code immernoch lesbar sein und auch dieses manko beheben.
Ja, zumindest mit gcc auf 32bit-Architekturen funktionieren derartige Tricks meist.
Mit defines kann man das ja Konfigurieren, welche bitfelder genommen werden, je nach Prozessor ... Hmm, sehr problematisch, da der Prozessortyp alleine keinen Rückschluss darüber erlaubt wie Bitfelder angeordnet werden.
In vielen Fällen reicht es allerdings die Endianness/Byteorder zu analysieren, (Manche Prozessoren können mehrere "Endiannesses"; dort ist Endianness normalerweise ein Compiler-Flag). Es gibt aber auch noch exotischere Systeme, in denen das nicht ausreicht (Fragestellung der Wortbreite einer Architektur: 8/16/32/64bit; VAX-Byteorder. Structure-Alignment u.ä.) Der Work-around ist allerdings einfach: Entweder auf I/O von Bitfeldern verzichten oder nur Ordinaltypen und Bit-Ops verwenden (Diese sind portabel und haben keine Byteorder/Alignment-Probleme.) Ralf
Hi Ralf,
From: "Ralf Corsepius"
Am Mon, 2003-05-19 um 11.41 schrieb Andre Heine:
From: "Ralf Corsepius"
Am Sam, 2003-05-17 um 16.23 schrieb Andre Heine:
[...]
Aber wenn ich ein Bitfeld habe, wo ich "union.bittyp.bit0 = 1" setze, muss das ist immer so sein!
Ich meine, es ist egal das der Compiler das nun rechts oder links anordnet. bit0 im struct ist immer '1'. Jein, solange Du diese Struct nur als interne Datenstruktur verwendest spielt es keine Rolle. Sobald aber I/O ins Spiel kommt, sieht die Sache anders aus.
Was genau meinst du mit I/O, Dateien oder I/O an einem Port, oder gar beides? Das verwirrt mich jetzt ein wenig ;( Habe ich z.B. einen Port, der 8 Bit breit ist und jeden Pin mit ein bit zugeordnet, dann ändert das doch nichts *wunder*. Da ist doch immer PIN 8 = bit7 (jenachdem wie ich das Verknüpfe ....) Meinst Du das als "interne Datenstruktur"?
In meinen Beispiel benutze ich in einer "union" eine "unsigned char" mit einem Bitfeld, d.h, wenn nun der Compiler die Bits anders für das "unsigned char" anordnet, ist das natürlich fatal, weil eben die Reihenfolge anders ist.
Das wird ein BUG im Programm, den ich nicht gerne suchen möchte :)) ;) Ja, soetwas ist teuflisch zu suchen.
( Wer denkt sofort an die Bitausrichtung, na gut Ralf schon *Grins* ) Ach, diesen Diesen Punkt erreicht man schnell, wenn man sich mal mit Hardware-naher Programmierung oder mit Kommunikation zwischen verschiedenen OSen und/oder Architekturen beschäfftigt. -- Ich bin in beiden Feldern zu Hause.
Man lernt dann schnell scheinbar elegante Tricks ähnliche diesem hier zu vermeiden:
union { unsigned int i; struct { unsigned char pad0:7; unsigned char c7:1; unsigned char c8:1; unsigned char pad:5; unsigned char c13:1; unsigned char ; unsigned char c20:1; } u; } mytype ;
Frage: An welchem Bit in i steht c13?
In der Tat nicht einfach, die Union hat einen anderen Typ als das struct und damit unterschiedliche lange Typen. Ich weiss auch nicht, was der Compiler mit dem "leeren" Bit macht, wird das angehängt oder an die korrekte Position gestellt? AFAIR wird es an die korrekte Position gestellt, so wie ich C kenne ist das bestimmt wiedermal von irgendetwas abhängig ;( Muss die Länge des "unbenutzten Bit" nicht mit angegeben werden? z.B: 'unsigned char : 1' Obige union lässt sich bei mir ohne die Länge nicht kompilieren... Gemein ist auch, das in Deinem struct die Längenangaben nicht wirklich zu dem "unsigned char" passen (aber zu dem unsigned int der union). Wolltest du darauf anspielen? Bitte die Auflösung :))))
D.h. so bald C-Bitfelder binär ausgegeben werden sollen oder Hardware mit Bitfeldern angesteuert werden sollen, wird der Code unportabel.
Das habe ich, ehrlich gesagt, gar nicht bedacht... Da brauche ich eigentlich nur die vorhandenen Bitfelder "umdrehen" und schon sollte mein Code immernoch lesbar sein und auch dieses manko beheben.
Ja, zumindest mit gcc auf 32bit-Architekturen funktionieren derartige Tricks meist.
Das würde zwar reichen, aber jetzt fange ich an zu überlegen *grummel* Doch alle Bitfelder raus und durch "Bit Ops" ersetzen? Ciao Andre
Am Mon, 2003-05-19 um 16.24 schrieb Andre Heine:
Hi Ralf,
From: "Ralf Corsepius"
Am Mon, 2003-05-19 um 11.41 schrieb Andre Heine:
From: "Ralf Corsepius"
Am Sam, 2003-05-17 um 16.23 schrieb Andre Heine:
[...]
Aber wenn ich ein Bitfeld habe, wo ich "union.bittyp.bit0 = 1" setze, muss das ist immer so sein!
Ich meine, es ist egal das der Compiler das nun rechts oder links anordnet. bit0 im struct ist immer '1'. Jein, solange Du diese Struct nur als interne Datenstruktur verwendest spielt es keine Rolle. Sobald aber I/O ins Spiel kommt, sieht die Sache anders aus.
Was genau meinst du mit I/O, Dateien oder I/O an einem Port, oder gar beides? Beides. Irgendeine _binäre_ Ein- oder Ausgabe.
Habe ich z.B. einen Port, der 8 Bit breit ist und jeden Pin mit ein bit zugeordnet, dann ändert das doch nichts *wunder*. Da ist doch immer PIN 8 = bit7 (jenachdem wie ich das Verknüpfe ....) Die entscheidende Frage hier wäre: Liegt bit0/bit7 im LSB oder MSB? Liegt bit0 auch im LSB der union?
Es ist implementationsabhängig.
Meinst Du das als "interne Datenstruktur"? Mit interner Datenstruktur war gemeint, dass Du dein C-Bitfelder nur innerhalb von Applikationen/Libs verwendest und sie nicht direkt ausgibst.
In meinen Beispiel benutze ich in einer "union" eine "unsigned char" mit einem Bitfeld, d.h, wenn nun der Compiler die Bits anders für das "unsigned char" anordnet, ist das natürlich fatal, weil eben die Reihenfolge anders ist.
Das wird ein BUG im Programm, den ich nicht gerne suchen möchte :)) ;) Ja, soetwas ist teuflisch zu suchen.
( Wer denkt sofort an die Bitausrichtung, na gut Ralf schon *Grins* ) Ach, diesen Diesen Punkt erreicht man schnell, wenn man sich mal mit Hardware-naher Programmierung oder mit Kommunikation zwischen verschiedenen OSen und/oder Architekturen beschäfftigt. -- Ich bin in beiden Feldern zu Hause.
Man lernt dann schnell scheinbar elegante Tricks ähnliche diesem hier zu vermeiden:
union { unsigned int i; struct { unsigned char pad0:7; unsigned char c7:1; unsigned char c8:1; unsigned char pad:5; unsigned char c13:1; unsigned char ; Typo: Da hätte unsigned char pad1; stehen sollen.
unsigned char c20:1; } u; } mytype ;
Frage: An welchem Bit in i steht c13?
In der Tat nicht einfach, die Union hat einen anderen Typ als das struct und damit unterschiedliche lange Typen. Ich weiss auch nicht, was der Compiler mit dem "leeren" Bit macht, wird das angehängt oder an die korrekte Position gestellt? War ein Typo (Siehe oben).
Bitte die Auflösung :)))) Es ist implementationsabhängig und hängt von einer Vielzahl von Faktoren ab. [Stichworte: Endianness, Struct-Alignment, Packing u.v.a.]
Einfaches Beispiel:
#include
D.h. so bald C-Bitfelder binär ausgegeben werden sollen oder Hardware mit Bitfeldern angesteuert werden sollen, wird der Code unportabel.
Das habe ich, ehrlich gesagt, gar nicht bedacht... Da brauche ich eigentlich nur die vorhandenen Bitfelder "umdrehen" und schon sollte mein Code immernoch lesbar sein und auch dieses manko beheben.
Ja, zumindest mit gcc auf 32bit-Architekturen funktionieren derartige Tricks meist.
Das würde zwar reichen, aber jetzt fange ich an zu überlegen *grummel* Doch alle Bitfelder raus und durch "Bit Ops" ersetzen? Das wäre ein anderes Extrem. Wenn Du Bitfelder nicht binär ein- und ausgibst, vorwiegend einzelne Bits auswertest, Geschwindigkeit und Portabilität nicht im Vordergrund stehen, Du wert auf übersichtlichen, wartbaren Code legst, spricht nicht viel gegen C-Bitfelder.
Wenn Du HW-nahen Code (Treiber o.ä.), geschwindigkeitskritischen Code (Kernel, libc, Signalverarbeitung o.ä.) schreibst und/oder binärer I/O im Vordergrund steht, würde ich zu Ordinaltypen mit Masken greifen. Ralf
From: "Ralf Corsepius"
Am Mon, 2003-05-19 um 16.24 schrieb Andre Heine:
[...]
Ich meine, es ist egal das der Compiler das nun rechts oder links anordnet. bit0 im struct ist immer '1'. Jein, solange Du diese Struct nur als interne Datenstruktur verwendest spielt es keine Rolle. Sobald aber I/O ins Spiel kommt, sieht die Sache anders aus.
Was genau meinst du mit I/O, Dateien oder I/O an einem Port, oder gar beides? Beides. Irgendeine _binäre_ Ein- oder Ausgabe.
Habe ich z.B. einen Port, der 8 Bit breit ist und jeden Pin mit ein bit zugeordnet, dann ändert das doch nichts *wunder*. Da ist doch immer PIN 8 = bit7 (jenachdem wie ich das Verknüpfe ....) Die entscheidende Frage hier wäre: Liegt bit0/bit7 im LSB oder MSB? Liegt bit0 auch im LSB der union? Es ist implementationsabhängig.
Oh NO, ich habe voll auf der Leitung gestanden ;( Jetzt verstehe ich hoffentlich besser ...
Einfaches Beispiel:
#include
union io { unsigned char c; struct { unsigned char c0:1; unsigned char c1:1; } bit ; };
int main() { union io my = { 0 } ; my.bit.c0 = 1; printf( "Ergebnis: %x\n", my.c ); return 0; }
Unter i386-pc-linux-gnu: # ./bla Ergebnis: 1
Unter sparc-sun-solaris: # ./bla Ergebnix: 80
Meine Applikation holt anhand eines UI diverse Einstellungen und setzt die Bits (wie in Deinem Beispiel). my.bit.c0 = 1 // toggled z.B ein Port Sind alle Einstellungen gemacht wird das 'unsigned char c' auf das Device geschrieben. (Das Kernel-Modul benutzt keine Bitfelder). Würde ich "my.c" nun mit printf ausgeben, bekomme ich aber unterschiedliche Ausgaben auf den unterschiedlichen Maschinen. So ist das nach meiner jetzigen Sicht OK. Würde ich aber z.B. einfach "my.c" mit z.B. auf '1' setzen, ist das z.B. auf Deiner sparc fatal. (Leider habe ich das so in einigen Programmteilen gemacht.) Hier würde dann die Bitreihenfolge nicht mehr stimmen, weil ich es auf meinen i386 PC getestet habe und könnte sogar Hardware damit zerstören (oder auch tanzen lassen :)). Es ist nicht sichergestellt, dass z.B. my.bit.cN auch gesetzt ist! Hab' ich das nun ungefähr kapiert?
Das wäre ein anderes Extrem. Wenn Du Bitfelder nicht binär ein- und ausgibst, vorwiegend einzelne Bits auswertest, Geschwindigkeit und Portabilität nicht im Vordergrund stehen, Du wert auf übersichtlichen, wartbaren Code legst, spricht nicht viel gegen C-Bitfelder. Wenn Du HW-nahen Code (Treiber o.ä.), geschwindigkeitskritischen Code (Kernel, libc, Signalverarbeitung o.ä.) schreibst und/oder binärer I/O im Vordergrund steht, würde ich zu Ordinaltypen mit Masken greifen.
Nach unserer Diskussion bin ich mir nicht mehr so sicher, ob ich Bitfelder nehmen sollte. Die Gefahr, das das UI falsche Funktionen an/mit Hardware ausführt ist recht gross, wenn man Deine "warnungen" missachtet ;( Jedenfalls ist vorsicht geboten und ich werd' mir das ganze nochmal gut überlegen! ciao andre PS: Dank' für genauen Erläuterungen *dazugelernt*
Am Friday 16 May 2003 19:05 schrieb Andre Heine: Fehler, besser "unsigned char" :)
typedef struct { char bit0 : 1; char bit1 : 1; char bit2 : 1; char bit3 : 1; char bit4 : 1; char bit5 : 1; char bit6 : 1; char bit7 : 1; } t_Bit;
typedef union { char base; BitTyp field; } t_BitUnion;
participants (5)
-
Andre Heine
-
Bodo Kaelberer
-
Manfred Tremmel
-
Ralf Corsepius
-
Tim Oliver Wagner