Frage - Zeiger auf ein Bit?



  • Ich möchte eine Klasse für beliebig lange Integer konstruieren, dabei entstand das Problem wie ich es speichern sollte. Schließlich habe ich beschlossen den Speicher über 'malloc', 'realloc' und 'free' zu verwalten. Die Zahl soll in binärer Form gespeichet werden, da dies die effizientste Methode ist und zudem auch die standard Operatoren für diesen Datentyp neu definiert werden müssen und mir die Boolsche Arithmeitk dafür am sinnvollsten erscheint.

    Jedoch bin ich auf ein Problem gestoßen, da C++ kein StandardTyp besitzt welches nur 1-Bit lang ist, kann ich auch keinen Zeiger definiern, welcher
    1. auf ein beliebiges Bit im reservierten Bereich gesetzt werden kann und beim Auswerten der Speicheradresse nur den Zustand des einen Bits liefert und nicht wie ein bool-Zeiger 8-Bit ausließt.
    2. analog zu 1. muss auch eine Möglichkeit gegeben sein um ein bestimmtes Bit zu ändern.
    😞

    Nun brauche ich eine Idee, wie ich solch einen Zeiger bekomme, schießlich muss es ja irgend wie gehen. Sonnst könnte ich mir nicht vorstellen, da überhaupt ein Standard Datentyp existiert.

    MfG
    VoluntaryAssistance



  • Einen Zeiger auf ein Bit wirst du nie bekommen.

    Du kannst höchstens einen Zeiger auf eine Byte bekommen und dir dann ein Bit daraus holen.

    Ein Zeiger zeigt auf eine Speicherstelle und die sind auf PC´s alle Byteweise organisiert, die physikalischen Zugriffe finden derzeit sogar nur 32 Bit weise statt

    Und ob du in C++ mit free, alloc, realloc glücklich wirst wage ich zu bezweifeln, in C++ sind Solche Arbeiten besser über new und delete geregelt.



  • Angenommen ich habe einen Zeiger auf ein Byte, wie jedoch soll ich dann ein bestimmtes Bit extrahieren?
    Es wäre zu aufwendig für Operationen sollte ich erst das eingelesene Byte in einer 8-er bool Array mit jedem ArrayElement als ein "Bit" aufschlüsseln um damit Operatioen durchführen.
    Zudem wurde C auch zur Programierung von UNIX verwendet und ich denke irgend wie müssen damals damit auch Grunddatentypen wie int usw. entworfen worden sein und so etwas grundlegendes wurde bestimmt nicht bei der Weiterentwicklung enfrent.

    MfG
    VoluntaryAssistance



  • std::vector<bool> eventuell oder std::bitset



  • /* Gibt zurück ob das n-te Bit in einer Speicheradresse gesetzt ist */
    template<class T>
    bool inline bitop::isset(T* v, unsigned int const& n)
    {
    	return ( (*v) & (1<<n) ) > 0;
    }
    


  • wie wärs wenn du einfach ein int oder ein long als basis nimmst? also nicht zur basis 10 oder 2 rechnst sondern zur basis 2^16 oder 2^32, da kannst du dann richtig flott mit großen zahlen operationen ausführen.



  • borg schrieb:

    wie wärs wenn du einfach ein int oder ein long als basis nimmst? also nicht zur basis 10 oder 2 rechnst sondern zur basis 2^16 oder 2^32, da kannst du dann richtig flott mit großen zahlen operationen ausführen.

    klingt geil 👍



  • oder sowas in der art

    #define SET_BIT_IN_ARRAY(ptr,bit) (*((unsigned char*)ptr+bit/8)|=1<<(bit%8))
    
    int main() 
    { 
        char a[3] = {0,0,0};
    
        printf ("%02x, %02x, %02x\n", a[2], a[1], a[0]);
        SET_BIT_IN_ARRAY (a, 15); 
        printf ("%02x, %02x, %02x\n", a[2], a[1], a[0]);
    }
    


  • So, erst mal danke für die Antworten.

    FireFlow zu deinem Template hätte ich noch eine Frage.

    return ( (*v) & (1<<n) ) > 0;
    

    Was genau bewirkt (1<<n)?
    Ich nehme an, dass (1<<n) 1-Byte im Speicher reserviert und erst alle Bits auf Null setzt und anschließend das n-te Bit von hinten auf 1 setzt.
    Oder ist diese Anweisung anders zu verstehen?

    Über eine andere Basis habe ich auch schon nachgedacht, borg. Hatte dabei jedoch überhaupt keinen umsetzbaren Ansatz für grundlegende Operationen.

    net. Dein Ansatz um ein Bit zu setzten erschein vielversprechend, kompeliert fehlerfrei, jedoch bicke ich da nicht durch...:(
    Was tut "SET_BIT_IN_ARRAY(ptr,bit)" eigentlich genau?
    Die Variablen 'ptr' und 'bit', was haben sie für einen Datentyp?



  • VoluntaryAssistance schrieb:

    So, erst mal danke für die Antworten.

    FireFlow zu deinem Template hätte ich noch eine Frage.

    return ( (*v) & (1<<n) ) > 0;
    

    Was genau bewirkt (1<<n)?
    Ich nehme an, dass (1<<n) 1-Byte im Speicher reserviert und erst alle Bits auf Null setzt und anschließend das n-te Bit von hinten auf 1 setzt.
    Oder ist diese Anweisung anders zu verstehen?

    Das ist der Linksshift-Operator. Der schiebt die Bits um n Stellen nach links durch. 1 << n ist dann z.B. 2n.



  • Walli schrieb:

    Das ist der Linksshift-Operator. Der schiebt die Bits um n Stellen nach links durch. 1 << n ist dann z.B. 2n.

    Und wie sind dabei die folgenden oder vorangegenagenen Bits gesetzt?

    z.B.: 1<<3
    Sieht es dann so "00000l00" oder so "?????1??" aus?



  • VoluntaryAssistance schrieb:

    Walli schrieb:

    Das ist der Linksshift-Operator. Der schiebt die Bits um n Stellen nach links durch. 1 << n ist dann z.B. 2n.

    Und wie sind dabei die folgenden oder vorangegenagenen Bits gesetzt?

    z.B.: 1<<3
    Sieht es dann so "00000l00" oder so "?????1??" aus?

    Es kommen Nuller rein
    (sonst wärs ja nicht 2n sondern irgendwas anderes 🙂



  • WENN denn in dem Datentyp (der ja nicht angegeben wurde) die binäre Darstellung von 1 als "00000001" ist, dann bewirkt der 3-fache linksshift die Zahl "00001000".

    @net: das #define stößt mir sauer auf. Solche Präprozessoranweisungen sind C-stil und völlig veraltet, zuweilen sogar gefährlich (wers nicht glaubt lese Scott Myers' "effective C++")
    Das kann man aber genausogut in eine Funktion packen

    @VA: Wenn du eine Basis von z.B. einem Byte nimmst, kannst du in den Operatoren eine 2-byte-struktur benutzen (oder länger, short würde genügen). Die Rechnungen würden dann ganz simpel wie schriftliches Rechnen im Zehnersystem laufen, nur dass du nicht mehr die Ziffern von 0 bis 9 hast sondern von (0) bis (255). Kommst du dann beim Rechnen auf eine Zahl, die größer ist als 255, z.B. 300, dann wäre das (1)(54) genauso wie im Zehnersystem eine Zahl größer als 9 mit zwei Ziffern dargestellt werden muss. Das Rechnen mit Überschlag dass man in der Grundschule gelernt hat ist ganz automatisch auf andere Zahlensysteme übertragbar...



  • pumuckl schrieb:

    @net: das #define stößt mir sauer auf. Solche Präprozessoranweisungen sind C-stil und völlig veraltet, zuweilen sogar gefährlich (wers nicht glaubt lese Scott Myers' "effective C++")
    Das kann man aber genausogut in eine Funktion packen

    mein stil ist c-stil 😉
    man kanns aber auch lesbarer schreiben

    #define SET_BIT_IN_ARRAY(ptr,bit) \ 
    ( \
       *((unsigned char*)ptr + bit/8) |= 1<<(bit%8) \
    )
    


  • Ich benutze einfach den & Operator um auf einzelne Bits zuzugreifen. Grad letzte woche wieder angewandt.

    /*
          None  (X) = 0000 = 0x0
          North (N) = 0001 = 0x1
          South (S) = 0010 = 0x2
          West  (W) = 0100 = 0x4
          East  (E) = 1000 = 0x8
          All   (A) = 1111 = 0xF
    */
    
      // North if direction = ***1
      if((direction & 1) != 0) {...}
    
      // South if direction == **1*
      if((direction & 2) != 0) {...} 
    
      // West if direction == *1**
      if((direction & 4) != 0) {...}
    
      // North if direction == 1***
      if((direction & 8) != 0) {...}
    


  • Hab' jetzt einen leichter umsetzbaren Ansatz, wo ich die Standarddatentypen __int32 und __int64 als basis verwende. Muss zwar jetzt eine umständlichere Umrechnung durchführen, jedoch sollte es klappen...

    MfG
    VoluntaryAssistance


Anmelden zum Antworten