bits im char Array[] adressieren
-
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.