bits im char Array[] adressieren
-
Er fragte ja nach einer eleganten Art und Weise.

Wenn er es nicht gleich braucht, kann er es ja immer noch im Hinterkopf behalten, damit es ihm später einmal nützlich sein kann.
P.S. Es gibt auch noch
boost::dynamic_bitset. :p
-
std::vector<bool> ist böse und sollt enicht benutzt werden!
Frag mich jetzt nicht nach den Gründen, aber es gab gute devfür, die damit zu tun hatten, dass es eine Template-spezialisierung ist.
stattdessen, sollte man std::bitset benutzen.
-
vlad_tepesch schrieb:
std::vector<bool> ist böse und sollt enicht benutzt werden!
Frag mich jetzt nicht nach den Gründen, ...Das macht deine Behauptung äusserst glaubwürdig...

vlad_tepesch schrieb:
stattdessen, sollte man std::bitset benutzen.
Sicher, weil man ja immer zur Compilezeit die Grösse weiss.
-
vlad_tepesch schrieb:
std::vector<bool> ist böse und sollt enicht benutzt werden!
wieso?
Frag mich jetzt nicht nach den Gründen
oh, sorry.
-
danke erstmal an alle für die Tips!
ich werde es heute angesprochenes auprobieren -> std::bitset hört sich gut anMein Programm ist nur eine Scnittstelle zu einem Gerät in Form einer Programmbibliothek.
Es werden 8 Byte hin und her gesendet mittels array[8].
User wird in seinem programm (C, BASIC, ..) bestimmte bits im array[8] auf 1 oder 0 setzen und danach versenden.DLL ist allgemein zu halten. Es muss für User möglich sein die Namen für die Bits selbst zu definieren.
Ich könnte also sowas machen:union { struct { char bit0: 1; cahr bit1: 1; ... char bit7: 1; }byte; char byte0; ... cahr byte7; }Bytes; Bytes.byte0.bit0 = 1; //nun möchte ich, dass User diesen ganzen Bit/Byre Kramm //nicht zu sehen bekommmt, für Bytes.byte0.bit0 soll er selbst namen vergeben. //irgendwas in diese Richtung char* User_Def_Name_1 = &Bytes.byte0.bit0; //weiß nicht ob das geht ... char* User_Def_Name_64 = &Bytes.byte7.bit7; //für Bitmanipulation sollen dem user nur zwei Funktionen //zur Verfügung stehen //Bits auf 1 setzen set_bit(User_Def_Name_1,....User_Def_Name64); //Bits auf 0 setzen clear_bit(User_Def_Name_1,....User_Def_Name64);Hat jemand eine Idee wie ich es elegant schaffen kann, dass der Benutzer
die NAmen für Bits festlegen kann.
-
Wie wäre es, wenn du den Benutzer einfach ein Enum erstellen lassen könntest? Dann kann er wahlweise auch mit Zahlen zugreifen.
enum Bit { UserDef0, UserDef1, ... UserDef63 };Jetzt können die Funktionen folgendermassen aufgerufen werden:
set_bit(UserDef12, true); set_bit(12, true); set_bit(8*1 + 4, true);Der letzte Fall ist für die Übersichtlichkeit, wenn man die Gliederung behalten will. Wie ist es, soll der Anwender die Unterteilung in 8*8 Bit kennen oder hat er 64 indifferente Bits zur Verfügung? Denn wenn er die Unterteilung kennen sollte, kann man auch eine entsprechende Funktion schreiben:
void set_bit(char byte, char bit, bool value);Edit: UserDef64 auf 63 geändert.

-
Zusätzliche Elemente deines structs, beispielsweise std::string, für die Namen?
-
Nexus schrieb:
vlad_tepesch schrieb:
std::vector<bool> ist böse und sollt enicht benutzt werden!
Frag mich jetzt nicht nach den Gründen, ...Das macht deine Behauptung äusserst glaubwürdig...

vlad_tepesch schrieb:
stattdessen, sollte man std::bitset benutzen.
Sicher, weil man ja immer zur Compilezeit die Grösse weiss.
Kennst du Scott Meyers?
Der hat großartige Bücher geschrieben:
Effective C++(kostenlos hier: xxx)
More Effective C++
Effective STL (kostenlos hier: xxx )Item 18 des letztbesagten buchs empfielt "Avoid using vector<bool>"
der Absatz beginnt mit:
Scott Meyers schrieb:
As an STL container, there are really only two things wrong with vector<bool>. First,
it's not an STL container. Second, it doesn't hold bools.Jetzt weiß ich auch wieder wo das problem war:
vector<bool> ist eine template spezialisation.
Tatsächlich ist es ein intvector, der bei zugriffen die bits aus den ints fummlet und dann als bool zurückgibt.
Das hat zur Folge, dass du von einem Vectorelement keinen Pointer hohlen und keine Referenz anlegen kannst, da immer ein lokales neues bool erzeugt wird.vector<bool> vec(15, true); bool& elem = vec[5]; elem = false; // <- das hat keinen einfluss auf das element im Vector. bool* bptr = &vec[2]; *bptr = falsE; // <- das hat ebenfalls keinen einfluss auf das element im Vector.Das sind so lauter spezialfälle, an die man nicht denkt, wenn man ahnungslos einen vector<bool> erzeugt.
Normalerweise würde man ja annehmen, dass er sich wie ein vector<irgendwas> verhält nur halt mit bools statt irgendwas.Edit:
hier noch ein äußerst gehaltvoller Download:
Effective c++ CD (CD mit Effective C++, More Effective C++, sowie artikeln und codebeispielen)
xxx@mod:
vielleicht sollte man die links in irgendeine faq eintragen, falls es noch nix gibt.
Die bücher sind auf jeden Fall sehr informativ.Edit 2:
ok, hab grad noch mal nachgelesen:
das ein lokales bool zurückgegeben wird, stimmt so auch nicht ganz. Es wird irgend ein Proxyobject zurückgegeben, weswegen der oben geschriebenen Code nicht mal compilieren sollte.
aber lests euch am besten selbst durch.Edit 3:
da ich jetzt doch an der legalität von knowfree zweifle, hab ich die links wieder entfernt.
-
Scott Meyers schrieb:
As an STL container, there are really only two things wrong with vector<bool>. First,
it's not an STL container. Second, it doesn't hold bools.Scott wollte wohl eher darauf aufmerksam machen, dass vector<bool> nicht unbedingt das macht was man, auf den ersten Blick, erwarten würde: Nämlich eine Liste von bool'schen Typen bereitstellen.
Aber an dieser Stelle ist die Funktionalität genau die, die man wünscht. Lediglich der Name kann verwirrend sein, ansonsten seh ich kein Argument gegen den Einsatz von vector<bool>.Wenn der Name stört (oder ggf die spezialisierte Variante aus dem Standard entfernt werden sollte) kann man sich ja per Typendefinition abhelfen.
-
vlad_tepesch schrieb:
(kostenlos hier: xxx)
Ich würde auch den Verweis "kostenlos hier" entfernen, diese Bücher sind nicht legal frei erhältlich.
cu André
-
vlad_tepesch schrieb:
Jetzt weiß ich auch wieder wo das problem war:
Okay, dann glaube ich dir jetzt.

War vorhin nicht böse gemeint, aber ich habe an deiner Aussage gezweifelt, weil ich noch nie etwas diesbezüglich gehört habe und du keine Argumente gebracht hast. Aber gut, so habe ich wieder was gelernt.
Trotzdem stimme ich David_pb zu. Gerade wenn man nur die Standardbibliothek benutzt und ein dynamisches Bitset will, ist
std::vector<bool>okay. Und weil es eine Templatespezialisierung ist, kann man auch erwarten, dass sich das Verhalten irgendwie vom normalenvector-Klassentemplate unterscheidet. Auf www.cplusplus.com ist die Sache beispielsweise gut erklärt.
-
hab das ganze vorerst so gelöst (grobe skizze):
#include <iostream> #include <bitset> void set_bit(int test1 = 0, int test2 = 0, int test3=0) { char data[8]; int test_cnt[8]; int i; test_cnt[0]=test1; test_cnt[1]=test2; test_cnt[2]=test3; //init data for(i=0;i<7;i++) data[i]=0x00; for(i=0;i<8;i++) { if(0<test_cnt[i]<8) { data[0]|=test_cnt[i]; } if(7 < test_cnt[i] < 16) { test_cnt[i]=test_cnt[i]-8; data[1]|=test_cnt[i]; } if(15 < test_cnt[i] < 24) { test_cnt[i]=test_cnt[i]-16; data[2]|=test_cnt[i]; } if(23 < test_cnt[i] < 32) { test_cnt[i]=test_cnt[i]-24; data[3]|=test_cnt[i]; } } }; int main() { //für user verfügbare variablen (evtl. als defines) const int a= 8; const int b= 17; const int c= 28; //user eigene variablen (änderung der varsnamen von oben) int LED1 = a; int LED2 = b; int POWER = c; set_bit(LED1, POWER); set_bit(LED1, LED2); }bin mit den ganzen ifs nicht ganz glücklich, deshalb werden daran noch
arbeiten um es eleganter zu lösen.danke an alle für Support
-
Die vier If-Abfragen könntest du wenigstens noch zu einer Schleife zusammenfassen.
Zudem:
//für user verfügbare variablen (evtl. als defines) const int a= 8; const int b= 17; const int c= 28; //user eigene variablen (änderung der varsnamen von oben) int LED1 = a; int LED2 = b; int POWER = c;Wieso nimmst du hier nicht Enumerationen?
#definewäre wohl die hässlichste Lösungsvariante.enum BitAccessor // BitAccessor ist auch gleich ein Typ. { a = 8, b = 17, c = 28, };Oder du lässt den User gleich das Enum selbst erstellen. Wieso soll er nochmals Variablen mit anderem Namen, die aber nichts bringen, kreieren?
Und wenn du schon
<bitset>inkludierst, könntest du es auch gleich benutzen.
-
@Hazzard_2009: Was hast du gegen mein Vorschlag?
bool GetBit( const char* data, int bit ) { return data[ bit >> 3 ] & 1 << ( bit & 7 ); } void SetBit( char* data, int bit ) { data[ bit >> 3 ] |= 1 << ( bit & 7 ); }Edit:
Dein Code hat übrigens Fehler, wenn a, b und c die zu setzenden Bits sein sollen.
-
Wieso nimmst du hier nicht Enumerationen
stimmmt. das kommt mir sehr entgegen. werde ich nehmen
enum Leiterkarte // BitAccessor ist auch gleich ein Typ. { a = 8, b = 17, c = 28, }; Leiterkarte lk1, kl2; //jede lk beinhaltet 60 leitungenWieso soll er nochmals Variablen mit anderem Namen, die aber nichts bringen, kreieren?
Genau die Namen sind's: Ich habe insgesamt 2 x60 Leitungen.
Im Gerät heißen sie A1,B1,C1 bis A30,B30,C30.
User soll in der lage sein diese Leitungen selbs zu benamen,
damit er im Code(Testprogramm) wissen kann was er da schaltet:
B28 sagt nix aus, LED1 oder POWER ist schon eindeutig.Was hast du gegen mein Vorschlag?
Funktionsaufruf muss so allgemein und einfach gehalten werden.
Deshalb auch variable Parameter zahl. Der User kann nur eine Leitung schalten,
oder gleich alle 120.
-
Und wenn du schon <bitset> inkludierst, könntest du es auch gleich benutzen.
hab mit sdt::bitset rumexperimentiert (nach vorschalg von David_pb)
und werde es weiterhin tun. hab aber für obige variante vergessen zu löschen
-
Hazzard_2009 schrieb:
Leiterkarte lk1, kl2; //jede lk beinhaltet 60 leitungenIch weiss nicht, ob du das falsch verstanden hast.
lk1undlk2beinhalten hier nur die Nummer (also einenint) des Enums. Da du diese nicht initialisierst, ist die Nummer nicht mal eine gültige Konstante derLeiterkarte-Aufzählung.Hazzard_2009 schrieb:
Genau die Namen sind's: Ich habe insgesamt 2 x60 Leitungen.
Im Gerät heißen sie A1,B1,C1 bis A30,B30,C30.
User soll in der lage sein diese Leitungen selbs zu benamen,
damit er im Code(Testprogramm) wissen kann was er da schaltet:
B28 sagt nix aus, LED1 oder POWER ist schon eindeutig.Aber wieso dann überhaupt A1, B1 und so? Lohnt sich die Abstraktion wirklich? Sonst kannst du ja gleich eine Funktion schreiben, die dir die Nummer des x-ten Bit aus dem y-ten Byte angibt.
char GetBitNumber(char Byte, char Bit) { return 8*Byte + Bit; }Finde ich persönlich schöner, als alle Konstanten zu duplizieren.