Bit-Abfrage



  • Hallo, ich hatte eine kleine Aufgabe wo ich übrprüfen sollte ob ein Bit gesetzt ist oder eben halt nicht. Eigentlich nichts Besonderes. Leider bin ich kolosal daran gescheitert und musste feststellen dass es an meinem Abfrage-Konstrukt lag. Habe jetzt ein Beispiel genohmen und stelle die Frage dort. Ist genau so bei mir passiert. Also erstes das Quellcode-Beispiel welches funktioniert.

    cout << "Eingabe einer Zahl: ";
    int zahl { 0 };
    cin >> zahl;
    int anzahlDerBytes { sizeof zahl };
    int anzahlDerBits { 8 * anzahlDerBytes };
    cout << " binär :  ";
    for (int k = anzahlDerBits - 1; k >= 0; --k) {
    	if ((zahl & (1 << k))) {
    		cout << '1';
    	} else {
    		cout << '0';
    	}
    }
    cout << '\n';
    

    Soweit ist Alles klar und nachvollziehbar. Jetzt der Code mit einer kleinen Änderung. Wieso funktioniert DAS nicht mehr?
    FEHLERCODE:

    cout << "Eingabe einer Zahl: ";
    int zahl { 0 };
    cin >> zahl;
    int anzahlDerBytes { sizeof zahl };
    int anzahlDerBits { 8 * anzahlDerBytes };
    cout << " binär :  ";
    for (int k = anzahlDerBits - 1; k >= 0; --k) {
    
    
    	if ((zahl & (1 << k)) == true) { // oder auch == 1  //geänderte Zeile
    
    
    		cout << '1';
    	} else {
    		cout << '0';
    	}
    }
    cout << '\n';
    

    Die Überprüfung auf FALSE klappt wieder, ich muss dann nur das COUT tauschen. Die Frage bleibt aber trotzdem: WIESO klappt das mit der Abfrage auf TRUE nicht?



  • Weil

    (zahl & (1 << k))
    

    nur 1 ist, wenn k==0 und das LSB von zahl gesetzt ist.

    (zahl>>k) & 1
    


  • HMMM danke für die INFO. Leider checke ich gerade garnichts. Werde mir das wohl noch einmal genauer ansehen müssen mit dem LSB. Trotzdem vielen Danke, vielleicht raff ich es bald noch😁
    Deswegen haben wohl die ganzen ungerade Zahlen bei der Eingabe eine "1" als ausgabe gebracht. Verstehe es immer noch nicht aber das kommt bestimmt noch.



  • @uuuguuug sagte in Bit-Abfrage:

    if ((zahl & (1 << k)) == true) {

    wird zu

    if ((zahl & (1 << k)) == static_cast<int>(true)) {
    

    da bei einem Vergleich beide Seiten auf die gleiche Größe gebracht werden. Du vergleichst also eine Zahl mit einer anderen statt auf wahr/falsch zu testen.

    Schreibe nie if( irgendwas == true ) .



  • Danke für die Erklärung, denke dass mir die Erläuterung weiterhelfen wird.



  • Bei (zahl & (1 << k) kommt nicht nur 0 oder 1 als Ergebnis heraus, sondern durch die Maskierung 0 oder 2k2^k.
    Und durch den expliziten Vergleich auf true (oder 1) wird eben nur bei k = 0 die Bedingung wahr.



  • @manni66 Hallo, wenn ich nichts falsch gemacht habe hat deine Änderung leider nichts bezweckt...
    Eine Frage habe ich immer noch bevor ich mir weiter mein Gehirn malträtiere. Wieso funktioniert das Beispiel ganz am Anfang des Beitrage noch wo nicht explizit auf TRUE oder FALSE geprüft wird?

    lg der UuugUuug



  • @uuuguuug sagte in Bit-Abfrage:

    @manni66 Hallo, wenn ich nichts falsch gemacht habe hat deine Änderung leider nichts bezweckt...

    Das ist keine Änderung, sondern das, was der Compiler implizit macht. Das kann nicht funktionieren.

    Wenn du unbedingt den Vergleich auf true willst (lass es!) dann musst du selber nach bool casten:

    if (static_cast<bool>(zahl & (1 << k)) == true) {
    


  • Danke dir auch noch einmal, das hilft auch wieder ein Stück weiter. Und NEIN ich will das nicht unbeding TUN sondern einfach verstehen was da so abgeht.... 😆
    Das Bespiel hat jetzt endlich auch funktioniert. Jetzt wirklich die allerallerletze Frage. Wieso sollte ich es nicht expilzit so machen wie du es mir gezeigt hast, was ja auch funktioniert, da es der Comiler ja genau so implizit zu tun scheint?.
    War definitiv die letzte Frage.



  • Die generelle Abfrage if (x) entspricht einem Vergleich auf != 0, d.h. if (x != 0). Und daher funktioniert es bei dir, wenn du auf false (bzw. 0) testest und die Anweisungen vertauschst (da im else-Fall dann "ungleich Null" gilt).



  • Ganz kurz:

    Die Frage, ob etwas ungleich 0 ist, ist nicht dasselbe wie ob etwas gleich 1 ist.
    Zum Beispiel ist 2 ungleich 0, aber 2 ist nicht gleich 1.

    if (zahl) vergleicht auf ungleich 0, ist also dasselbe wie if (zahl != 0).
    if (zahl == true) wandelt true in eine Zahl um (nämlich 1) und vergleicht dann, es wird also zu if (zahl == 1).

    Jetzt endlich klar?



  • @uuuguuug sagte in Bit-Abfrage:

    Wieso sollte ich es nicht expilzit so machen wie du es mir gezeigt hast, was ja auch funktioniert, da es der Comiler ja genau so implizit zu tun scheint?.

    Wenn du damit meinst warum du nicht if (static_cast<bool>(zahl & (1 << k))) schreiben solltest? Weil das kein Mensch lesen will. Schreib if (zahl & (1 << k)). Oder wenn du es etwas "expliziter" haben willst: if ((zahl & (1 << k)) != 0).

    Die Variante mit dem static_cast<bool> ist zwar korrekt und funktioniert, aber total unüblich und daher verwirrend bzw. behindert den Lesefluss. In der Software-Entwicklung ist es wie auch bei anderen Ingenieurtätigkeiten wichtig sich an übliche Muster zu halten. Weil Konstruktionen die das nicht tun für erfahrene Ingenieure schwerer zu "lesen" sind.



  • @uuuguuug sagte in Bit-Abfrage:

    Wieso sollte ich es nicht expilzit so machen wie du es mir gezeigt hast, was ja auch funktioniert, da es der Comiler ja genau so implizit zu tun scheint?.

    Welche zusätzliche Information liefert dir das ganze Geschwätz, dass du dann schreiben musst? Hättest du den Versuch mit == true gar nicht erst unternommen, hättest du viel Zeit gespart.

    Siehe auch Don’t add redundant == or != to conditions



  • ich wusste es einfach nicht besser und die Abfrage auf TRUE war für mich soweit logisch aber wie gesehen falsch. Ich denke dass Thema hier kann geschlossen werde.

    Gruss der UuugUuug



  • @uuuguuug sagte in Bit-Abfrage:

    ich wusste es einfach nicht besser und die Abfrage auf TRUE war für mich soweit logisch

    Im Prinzip hast du recht, aber es ist halt C


Log in to reply