Bits lesen/setzen



  • Heyho,

    Ich arbeite momentan an einem kleinen Gameboy Emulator in C++ mit SDL.
    Ich habe allerdings momentan ein Problem.

    Ich möchte die einzelnen Bits aus z.B. einem unsigned char (u8) auslesen.
    Momentan benutze ich dafür diese Funktionen:

    u8 RegisterSet::getBit(int bitNum, u8 variable)
    {
        return variable & (1 << bitNum-1);
    }
    
    u8 RegisterSet::setBit(u8 Variable, int bitNum, u8 newValue)
    {
        Variable |= newValue<<bitNum;
        return Variable;
    }
    

    Allerdings scheint das nicht so ganz zu funktionieren.
    Die Möglichkeiten, die einzelnen Bits zu lesen oder zu setzen habe ich durchs googeln gefunden, aber es funktioniert nicht wirklich

    Hat jemand vielleicht eine Idee?



  • 1. Wieso nimmst du u8 statt unsigned char?
    Ist doch c++11, wenn ich mich recht erinnere?

    2. IIRC meinst du das:

    z.b. hast du einen char, wert 64, Binäre Codierung:

    01000000 (oder so ähnlich, egal.)

    Zweites Bit von Links soll gesetzt werden, folgendermaßen:

    setbit(namedeschars, nummerdesbits, neuerwert);
    setbit(name, 2, 1);

    Müsste newvalue dann nicht ein Boolean sein?
    Bitte korrigier mich, wenn ich's falsch verstanden hab.

    Edit:
    Gibt hier nen schönen Text dazu. Ich würd es so lösen:
    Willst du z.b. den 2 Wert des obigen Beispiels nun setzen, nutzt du den |-Operator:

    01000000
    | 00000010
    ----------
      01000010
    

    Willst du die Gültigkeit eines Bits herausfinden, gehts folgendermaßen:

    01000000
    & 00000010
    ----------
      00000000
    

    Also prüfen ob der zurückgegebene Wert größer 0 ist.

    Ach ja, und nochwas: inwiefern ist es falsch?



  • Hacker schrieb:

    1. Wieso nimmst du u8 statt unsigned char?
    Ist doch c++11, wenn ich mich recht erinnere?

    Weil ein char nicht 8 Bit groß sein muss.

    Spongy: Der Code funktioniert, vielleicht auch nicht so, wie du das willst, und nicht konsistent in der Bitbenennung. Aber um dir zu helfen, müsstest du sagen, wie du die Bits durchnummerieren willst und ob "setzen" auch "auf 0 setzen können" heißt.



  • u8 ist lediglich ein typedef auf unsigned char.

    newValue ist ein unsigned char und kein bool, weil ich mit einem Boolean die Bitweise verschiebung nicht durchführen könnte, oder?

    Ich weis nicht, wie ich die Richtigen masken mit den angaben die ich in der Funktion kriege "errechnen" lassen soll.



  • Zu deiner Get-Funktion:

    Das "bitNum-1" ist Quatsch. Damit bist du inkonsistent zu deiner Set-Funktion. Lasse es ruhig nullbasiert. Das 1er-Bit ist also das nullte. Außerdem hat Hacker recht, hier macht u8 nicht überall Sinn. Die Rückgabe von der Get-Funktion sollte bool sein, denke ich. Du willst ja schließlich wissen, ob das Bit gesetzt ist. Wenn bei dir Bit 2 gesetzt ist, kriegst du nicht 1 oder true, sondern 4 zurück. Macht wenig Sinn.



  • Komisch. Mein Compiler spuckt aus, u8 gibt's garnich.

    bool getBit(int bitNum, unsigned char variable)
    {
        return variable & (1 << bitNum-1);
    }
    
    void setBit(unsigned char& Variable, int bitNum, unsigned char newValue)
    {
        Variable |= newValue<<bitNum;
    }
    

    Setbit soll doch setzen?



  • Weils uint8_t heißt. Aber er kann ja auch z.B. selber typedef'n.



  • _matze schrieb:

    Zu deiner Get-Funktion:

    Das "bitNum-1" ist Quatsch.

    Nö.

    Damit bist du inkonsistent zu deiner Set-Funktion.

    Ja.

    Außerdem hat Hacker recht, hier macht u8 nicht überall Sinn. Die Rückgabe von der Get-Funktion sollte bool sein, denke ich. Du willst ja schließlich wissen, ob das Bit gesetzt ist. Wenn bei dir Bit 2 gesetzt ist, kriegst du nicht 1 oder true, sondern 4 zurück. Macht wenig Sinn.

    Kommt ganz auf deine Anwendung an.



  • Hacker schrieb:

    Komisch. Mein Compiler spuckt aus, u8 gibt's garnich.

    bool getBit(int bitNum, unsigned char variable)
    {
        return variable & (1 << bitNum-1);
    }
    
    void setBit(unsigned char Variable, int bitNum, unsigned char& newValue)
    {
        Variable |= newValue<<bitNum;
    }
    

    Setbit soll doch setzen?

    Und was passiert bei deinem Code wohl, wenn ich für newValue 35 angebe?



  • Geeditet 😃



  • Michael E. schrieb:

    _matze schrieb:

    Zu deiner Get-Funktion:

    Das "bitNum-1" ist Quatsch.

    Nö.

    Damit bist du inkonsistent zu deiner Set-Funktion.

    Ja.

    Ok, von mir aus: die dadurch erzeugte Inkonsistenz ist Quatsch. 🙄 Aber irgendwas ist Quatsch, ganz sicher! 😃



  • Also, ich habe jetzt folgenden Code:

    bool RegisterSet::getBit(int bitNum, u8 variable)
    {
    	return variable & (1 << bitNum-1);
    }
    
    void RegisterSet::setBit(u8 *Variable, int bitNum, u8 newValue)
    {
    	*Variable |= newValue<<bitNum;
    }
    

    Die getBit Funktion funktioniert schonmal, nur "falsch herum".
    Wenn ich Bit 7 abfrage kriege ich Bit 2.
    Die setBit Funktion arbeitet leider immernoch nicht korrekt.



  • Was benutzt du den Zeiger?
    Hascht du nix gelernt?
    Zeiger nur so wenig wie möglich benutzen. Lieber Referenzen.



  • Hacker schrieb:

    Was benutzt du den Zeiger?
    Hascht du nix gelernt?
    Zeiger nur so wenig wie möglich benutzen. Lieber Referenzen.

    Hier finde ich Zeiger auch besser.



  • wieso?



  • Habs fertig:

    void setBit(unsigned char& Variable, int bitNum, bool newValue)
    {
        Variable = Variable ^ 1 << bitNum;
    }
    

    Test:

    setBit(a, 5, 0);// a ist 57, ergebnis: 25
    //[..]
    setBit(a, 5, 1);//a is wida 57
    


  • Bloß schrieb:

    wieso?

    Weil ich beim AUfruf

    setBit(&a,5);
    

    am & sofort sehe, daß a verändert werden könnte.
    Das hilft mir bei der Fehlersuche.



  • Ich bin für die Referenz, da es keinen Sinn macht, einen Nullzeiger zu übergeben.



  • Hmm volkard...
    ich glaub sogar, es soll verändert werden - nicht nur weil die Funktion 'set' im Namen trägt 😉
    Ein hoch auf die transzendente Zahl!



  • Habs ausprobiert:

    bool RegisterSet::getBit(int bitNum, u8 variable)
    {
    	return variable & (1 << bitNum-1);
    }
    
    void RegisterSet::setBit(u8 *Variable, int bitNum, bool newValue)
    {
    	*Variable = *Variable ^ newValue<<bitNum;
    }
    
    u8 test = 64;
    theSet->setBit(&test, 6, 1); // Sollte Bit 6 auf 1 setzen -> 00000010 -> 00000110
    bool theBit = theSet->getBit(&test, 7); // test = 0 | theBit = 0
    

    Irgendwas läuft schief :S


Anmelden zum Antworten