Bits genau setzen ?



  • @BitFreak: Kannst du das mal Schritt für Schritt erklären? 👍



  • MasterCounter schrieb:

    @BitFreak: Kannst du das mal Schritt für Schritt erklären? 👍

    yo dafür wäre ich auch sieht hammer toll aus aber verstehen tue ichs net , mir wäre aber eine Erklärung zu meiner Frage mit der Bit Funktion lieber, da es einfacher ist...danke



  • MasterCounter schrieb:

    @BitFreak: Kannst du das mal Schritt für Schritt erklären? 👍

    p>>3 entspricht p/8. das ist der index ins byte-array, also mit a[p>>3] kommen wir an das richtige byte im array. das gesuchte bit-index in diesem byte ist der rest, der bei einer division durch 8 übrig bleibt. mit p&3 kriegt man diesen wert auch (0...7). um daraus das passende bit zu machen, schieben wir eine 1 so oft nach links: (1<<(p&3)). dann einfach mit |= das bit hinein-odern und fertig. BitGet und BitClear kann man dann so ähnlich machen.
    🙂



  • Pelle schrieb:

    MasterCounter schrieb:

    @BitFreak: Kannst du das mal Schritt für Schritt erklären? 👍

    yo dafür wäre ich auch sieht hammer toll aus aber verstehen tue ichs net

    Wie kann es toll sein wenn du es nicht verstehst? Erklär mir das mal bitte. Ich hab den Müll verstanden und finde es trotzdem nicht toll. Das ist einfach nur Frickelei (auf welchem Niveau auch immer). Sowas solltest du dir nicht abschauen. Das Problem ist nicht die Methode wie es gemacht wird. Das Problem ist die Umsetzung.
    Das ganze Ding kann man Lichtjahre lesbarer schreiben, ohne dabei Laufzeittechnisch groß zu verlieren. Alleine die Bezeichner a und p sind ja eine Frechheit. Eine Funktion würde auch nicht schaden, da könnte man temporäre Variablen für die Shifterei benutzen. etc. pp.



  • Tim schrieb:

    Pelle schrieb:

    MasterCounter schrieb:

    @BitFreak: Kannst du das mal Schritt für Schritt erklären? 👍

    yo dafür wäre ich auch sieht hammer toll aus aber verstehen tue ichs net

    Wie kann es toll sein wenn du es nicht verstehst? Erklär mir das mal bitte. Ich hab den Müll verstanden und finde es trotzdem nicht toll. Das ist einfach nur Frickelei (auf welchem Niveau auch immer). Sowas solltest du dir nicht abschauen. Das Problem ist nicht die Methode wie es gemacht wird. Das Problem ist die Umsetzung.
    Das ganze Ding kann man Lichtjahre lesbarer schreiben, ohne dabei Laufzeittechnisch groß zu verlieren. Alleine die Bezeichner a und p sind ja eine Frechheit. Eine Funktion würde auch nicht schaden, da könnte man temporäre Variablen für die Shifterei benutzen. etc. pp.

    Weil es beeindrucked ausssieht deshalb!(oh ich sehe gerade du wohnst bei mir um die Eck 😃 ) Man muss nicht alles verstehen um etwas toll zu finden bsp: Ein Flug zum Mond fände jeder Toll, doch warum vllt. ist die fahrt auch schrecklich verbunden mit übelkeit ists dann immer noch toll? Manche sagen Gott ist toll obwohl sie ihn nie gesehen haben 😃

    Yep das was bitfreak da schreibt ist für mich einen Anfänger frickelei der schlimmsten Art, jetzt wo du Tim es erwähnst als mod, trau ich mich auch es zu sagen :p wie gesagt ich habe ein Beispiel mit einer Funktion versteehs aber nur teilweise... siehe oben die Fragen...



  • Tim schrieb:

    Das ist einfach nur Frickelei...

    ok, dann mal eine schöne version

    void SetBit (unsigned char *array, unsigned int bitnummer)
    {
      unsigned int byte_position = bitnummer / 8;
      unsigned int bit_position = bitnummer % 8;
      unsigned int bit = (unsigned int)pow (2.0, bit_position);
      array[byte_position] = array[byte_position] | bit;
    }
    

    oder, besser noch, nimm C++ (std::bitset). C ist doch sowieso zu nix zu gebrauchen.
    🙂



  • Also mal noch ein paar Fragen dazu:

    Als Bitnummer gibt man die Nummer des Bits an, vom 0ten Array Element aus gezählt. Wenn ich jetzt vom 4. Array-Platz, das 4. Bit setzen will gebe ich
    3*8+4=28 als Bitnummer an. Die Nummer im Byte wird in deiner Funktion dann mit bitnummer/8 berechnet, also 28/8=3 (müsste doch eigentlich aber 4 sein?) und die Bitnummer in diesem Array dann mit 28%8=4. Aber dann setzt man doch im 3 Array das 4. Bit und nicht im 4. das 4..

    Für was ist dein "bit" dar gut? 2^4=16. Nur damit bit nicht 0 ist und das Bit somit gesetzt wird? Weil das wird ja dann beim Oder Ausdruck verwendet. Reicht dann nicht einfach:

    array[byte_position] = array[byte_position] | 1;
    

    Eigentlich ja nicht, weil dann würde array[byte_position] ja immer nur den Wert 1 erhalten und nicht das Bit gesetzt werden... Hmmmmmm 😕

    Und | ist ja gar kein logischer Ausdruck -.- Aber was macht das Ding denn dann...



  • MasterCounter schrieb:

    (müsste doch eigentlich aber 4 sein?)

    naja, arrays fangen bei index 0 an und bits auch. deshalb ist's immer einer weniger als du erwartest.

    🙂



  • MasterCounter schrieb:

    Und | ist ja gar kein logischer Ausdruck -.- Aber was macht das Ding denn dann...

    das ist die logische 'oder' funktion. damit kann man gezielt einzelne bits auf 1 setzen. ich depp hätte übrigens stattdessen besser '+' verwenden sollen. das '|' ist auch wieder nur was für dumme frickler.
    🙂



  • naja, arrays fangen bei index 0 an und bits auch. deshalb ist's immer einer weniger als du erwartest.

    Das is richtig 😃

    Ah okay,

    array[byte_position] = array[byte_position] + bit;

    geht also auch. bit is in meinem beispiel 16 und die Position 3, also

    array[3] = array[3] + 16;

    heisst für mich aber jetzt soviel wie
    array[3] += 16;

    Und da wird doch dann nur der gesamte Wert verändert und doch nicht nur ein einzelnes Bit!?



  • 16 ist binär 10000. Hab bei 1 Anfangen zu Zählen, wollte das 4. verändern, verändere mit der Angabe 4 das 5. Bit, alles klar - Habs kapiert, Dankeschön!

    Aber wenn jetzt das 5. Bit schon auf 1 gesetzt ist und ich es nochmal setze (mit dem + ), wird das 5. doch Null und das 6. gesetzt, das würde ja bei der Version mit | nicht passieren, oder?



  • define Byte usigned char;

    Byte wert = 0;

    Aufruf:BitSet(&wert,0);

    void BitSet(Byte *val,Byte bit)
    {
      Byte test_val = 0x01; // test_val sieht so aus 0000 0001
      test_val = (test_val << bit); // aus 0000 0001 wird 0000 0010 ? 1x nach links?
      *val = (*val | test_val); // obiges Änderung 0000 0010 wird bitmäßig auf *val kopiert bzw. gesetzt
    }
    

    wenn die Funktion wie in meinem buch aufgerufen wird mit

    BitSet(&egal,0);
    

    dann wird die Zahl 1 in 0000 0001 gar nicht nach links geschoben richtig? 0 heißt ja 0 mal nach links bzw. 0 stellen öhm was hat die "0" dann für einen Sinn?

    Kann mir auch jemand sagen, warum der Autor einen Zeiger für den 1. Parameter der Funktion nimmt?



  • #define PLAETZE 128
    #define BITS	  8 // Bits pro Byte
    
    // Ausgabe des 128 Bit Arrays.
    // Erste Zeile links: Bit Nr 1, rechts: Bit Nr 8.
    // Zweite Zeile links: Bit Nr 9, rechts: Bit Nr 16.
    // .
    // .
    // .
    // Letzte Zeile links: Bit Nr 121, rechts unten: Bit Nr 128
    
    void show128bit( char* p )
    {
    	int i,j;
    
    	for ( i=0; i<PLAETZE/BITS; i++ )
    	{
    		for ( j=0; j<BITS; j++ )
    		if ( p[i] & ( 1 << j ) ) printf("1"); else printf("0");
    		puts("");
    	}
    	puts("");
    }
    
    // 1 <= Nr <= 128
    void platz_reservieren( int Nr, unsigned char* p )
    {
    	if ( Nr < 1 || Nr > PLAETZE )
    	{
    		printf("Falsche Platznummer: %d", Nr );
    		return;
    	}
    	p[(Nr-1)/BITS] |= (1<<((Nr-1)%BITS));
    }
    
    // 1 <= Nr <= 128
    void platz_loeschen( int Nr, unsigned char* p )
    {
    	if ( Nr < 1 || Nr > PLAETZE )
    	{
    		printf("Falsche Platznummer: %d", Nr );
    		return;
    	}
    	p[(Nr-1)/BITS] &= ~(1<<((Nr-1)%BITS));
    }
    
    int main()
    {
    	int i=0;
    	unsigned char Lagerplaetze[PLAETZE/BITS];
    	unsigned char* p = Lagerplaetze;
    
    	// Alle Plätze Null setzen.
    	memset( p, 0, sizeof(Lagerplaetze) );
    
    	// Alle Plätze reservieren;
    	for ( i=1; i<=PLAETZE; i++ )
    	{
    		platz_reservieren(i,p);
    	}
    
    	platz_loeschen (128,p);
    
    	show128bit(p);
        return 0;
    
    }
    

    🙂



  • bit-freak schrieb:

    nimm doch ein array aus 8 bytes und dann...

    #define SetBit(a, p) ((a)[(p)>>3] |= (1<<((p)&3)))
    #define GetBit (a, p) (!!((a)[(p)>>3] & (1<<((p)&3))))
    

    sollte das nicht jeweils (1<<((p)&7)) heißen wenn du mod 8 berechnen willst...

    Tim schrieb:

    Ich hab den Müll verstanden und finde es trotzdem nicht toll. Das ist einfach nur Frickelei (auf welchem Niveau auch immer).

    quatsch mach ich auch immer so. um das "/8" und "%8" kommt man in dem fall nicht rum, wenn man also die bit-ops verstanden hat, warum nicht...



  • @YaB hui das sieht nett aus R3SP3KT 😃 doch eins hast du vergessen (vllt. hab ichs auch net erwähnt...) bevor ein bit gesetzt wird muss natürlich geprüft werden ob dieses bereits gesetzt ist, denn wenn ja muss ein anderer Lagerplatz ausgesucht werden im Anhaenger...

    Sonst schönes Beispiel, doch bei einigen Frickelein steigt mein Verstand aus...

    das ist für mich nicht mehr lesbar...

    p[(Nr-1)/BITS] &= ~(1<<((Nr-1)%BITS));
    

    Ich bitte um Berücksichtigung meiner Fragen siehe oben ...danke



  • scheise schrieb:

    bit-freak schrieb:

    nimm doch ein array aus 8 bytes und dann...

    #define SetBit(a, p) ((a)[(p)>>3] |= (1<<((p)&3)))
    #define GetBit (a, p) (!!((a)[(p)>>3] & (1<<((p)&3))))
    

    sollte das nicht jeweils (1<<((p)&7)) heißen wenn du mod 8 berechnen willst...

    Tim schrieb:

    Ich hab den Müll verstanden und finde es trotzdem nicht toll. Das ist einfach nur Frickelei (auf welchem Niveau auch immer).

    quatsch mach ich auch immer so. um das "/8" und "%8" kommt man in dem fall nicht rum, wenn man also die bit-ops verstanden hat, warum nicht...

    Du findest >>3 so lesbar wie /8? Und &3 so lesbar wie %4? Du findest a und p sind gute Bezeichner? Du findest !! lesbarer als ein (bool)(expression)? Du findest Makros besser als Funktionen? Und die wichtigste Frage: Was denkst du ist für Anfänger besser geeignet?



  • Du findest >>3 so lesbar wie /8? Und &3 so lesbar wie %4? Du findest a und p sind gute Bezeichner? Du findest !! lesbarer als ein (bool)(expression)? Du findest Makros besser als Funktionen? Und die wichtigste Frage: Was denkst du ist für Anfänger besser geeignet?

    Jetzt komm endlich ich zum Zug...(huch schon wieder...) Egal was Tim beides ist für Anfänger völlig ungeeignet. Ich weiß zwar dass meine Fragen generell hier nie beachtet werden warum auch immer doch ich stell einfach mal eine weitere...

    nehmen wir an wir hätten:

    unsigned int iLagerplaetze[4];
    

    Für alle Schlaumeier hier ganz bewußt: --> Die Routine läuft NUR und EXPLIZIT in der WINDOWS32 Konsolenkeksedose das heißt ein int hat hier IMMER 32 BiT!!!

    so...nehmen wir weiter an iLagerplaetze hat diese Belegung:

    00000000001000000000000000000000 = 32Bit
    00000000000000000100000000000000 = 32Bit
    00000100000000000100000001000000 = 32Bit
    00000000000010000000010000000000 = 32Bit

    und nun möchte ich Lagerplatz 128 reservieren sprich Bit 127...

    wie mache ich das mit folgender Funktion?

    Kann mir das jemand zeigen? und da soll man nicht pampig werden *pfeiff*...

    void BitSet(Byte *val,Byte bit)
    {
      Byte test_val = 0x01;
      test_val = (test_val << bit);
      *val = (*val | test_val);
    }
    


  • Pelle schrieb:

    dann wird die Zahl 1 in 0000 0001 gar nicht nach links geschoben richtig?

    richtig

    Pelle schrieb:

    0 heißt ja 0 mal nach links bzw. 0 stellen öhm was hat die "0" dann für einen Sinn?

    die funktion hätte gern einen parameter, möchte man das erste bit
    setzen, ist die funktion mit der 0 aufzurfen.

    Pelle schrieb:

    Kann mir auch jemand sagen, warum der Autor einen Zeiger für den 1. Parameter der Funktion nimmt?

    ja.
    der wert, der übergeben wird, soll ja verändert werden.
    ohne zeiger würde der wert nur in den parameter kopiert, aber nicht
    verändert werden.

    Pelle schrieb:

    das ist für mich nicht mehr lesbar...
    p[(Nr-1)/BITS] &= ~(1<<((Nr-1)%BITS));

    es geht ja darum das 128 bit array zu adressieren.

    hier ein beispiel mit 40 bit, von links nach rechts gelesen
    11111111|11111111|11111111|11111111|11111111

    mit p[0], p[1] usw springst du immer 8 bit, also ein byte weiter.
    p[0] adressiert die ersten 8 bit, p[1] die zweiten 8 usw.

    (Nr-1)/BITS ist eine integerdivision, der nachkommateil wird
    abgeschnitten, d.h. 1/BITS = 0, 2/BITS =0 ... 8/8 = 1, 9/8 = 1 usw.

    Nr kann werte von 1 bis 128 annehmen, demzufolge kann
    Nr-1 werte von 0 bis 127 annehmen
    damit kann (Nr-1)/BITS werte von 0 bis 15 annehmen.
    mit p[(Nr-1)/BITS]
    können wir also die byte-grenzen p[0] ... p [15] adressieren.

    um jetzt an die einzelnen bits ranzukommen, erstellt man sich eine
    bitmaske, die man mit dem array vernüpft.

    als rechenbeispiel möchte ich mal PlatzNr 9 löschen, also Nr = 9.
    (Nr-1)/BITS liefert mir: (9-1)/8 = 1, bekomme also p[1].
    das ist die linke seite des ausdrucks
    p[(Nr-1)/BITS] &= ~(1<<((Nr-1)%BITS)) <=> p[1] &= ~(1<<((Nr-1)%BITS))

    um an das bit ranzukommen erstelle ich die bitmaske:
    ~(1<<((Nr-1)%BITS)) wobei % der modulo-operator ist

    ((Nr-1)%BITS) ergibt: (9-1)%8 = 8%8 = 0

    erhalte also als zwischenergebnis auf der rechten seite im ausruck:
    ~(1<<(0)) <=> ~1

    vom dem gesamten ausdruck bleibt also übrig:
    p[1] &= ~1

    binär sieht das so aus:
    die eins wird negiert und ich erhalte, von links nach rechts gelesen:
    01111111

    schreibe ich p[1] binär, das ist der zweite byte-block,
    erhalte ich: 11111111

    11111111 & 01111111 ergibt 0111111, das ist der wert der in p[1] gespeichert
    wird.

    aus dem obigen 40 bit array wird also

    11111111|01111111|11111111|11111111|11111111

    damit hätte ich platz nr 9 gelöscht.
    🙂



  • Pelle schrieb:

    so...nehmen wir weiter an iLagerplaetze hat diese Belegung:

    00000000001000000000000000000000 = 32Bit
    00000000000000000100000000000000 = 32Bit
    00000100000000000100000001000000 = 32Bit
    00000000000010000000010000000000 = 32Bit

    und nun möchte ich Lagerplatz 128 reservieren sprich Bit 127...
    wie mache ich das mit folgender Funktion?
    Kann mir das jemand zeigen? und da soll man nicht pampig werden *pfeiff*...

    mit deiner BitSet funktion kannst 32 bits adressieren, wenn du den datentypen änderst:

    void BitSet( int *val,  int bit )
    {
      int test_val = 0x01;
      test_val = (test_val << bit);
      *val = (*val | test_val);
    }
    

    wobei auch verkürzt schreiben kannst:

    void BitSet( int *val,  int bit )
    {
      *val |= (0x01 << bit);
    }
    

    um einen 128 bit bereich adressieren zu können, musst du ja irgendwie durch ein array
    wandern können. dafür kannst du eine von den genannten möglichkeiten wählen.
    dieses mal werden die bits von rechts nach links gelesen:

    int ist_platz_reserviert( int Nr, unsigned int* p )
    {
    	return (p[(Nr-1)/32] & (1<<( (Nr-1)%32 )) );
    }
    
    void platz_reservieren( int Nr, unsigned int* p )
    {
    	p[(Nr-1)/32] |= (1<<( (Nr-1)%32 ));
    }
    
    void showbin( unsigned int* p )
    {
    	int i, j;
    	for ( i=0; i<4; i++ )
    	{
    	 	for ( j=31; j>=0; j-- )
    		{
    			if ( p[i] & ( 1 << j ) ) printf("1"); else printf("0");
    
    		}
    			puts("");
    	}
    	puts("");
    }
    
    int main()
    {
    	//31	   23	  	15		 7	Array-Index		Hex
    
    	//00000000|00100000|00000000|00000000   0				0x200000
    	//00000000|00000000|01000000|00000000   1				0x4000
    	//00000100|00000000|01000000|01000000   2				0x4004040
    	//00000000|00001000|00000100|00000000   3				0x80000
    
    	unsigned int iL[4] = { 0x200000, 0x4000, 0x4004040, 0x80000 };
    	int Nr = 128;
    
    	if ( ist_platz_reserviert( Nr, iL ) )
    		printf("Platz Nr. %d ist reserviert:\n", Nr );
    	else
    		printf("Platz Nr. %d ist nicht reserviert.\n", Nr );
    
    	showbin(iL);
    
    	platz_reservieren( Nr, iL );
    
    	if ( ist_platz_reserviert( Nr, iL ) )
    		printf("Platz Nr. %d ist reserviert:\n", Nr );
    	else
    		printf("Platz Nr. %d ist nicht reserviert.\n", Nr );
    
    	showbin(iL);
    
        return 0;
    }
    

    🙂



  • @Pelle:
    vielleicht könntest du deinen ursprünglichen gedanken wieder aufgreifen, statt einzelner bits ein array aus 128 chars zu verwenden. ich weiss ja nicht, wie viel speicher deine umgebung hat, aber 'nem ausgewachsenen PC z.b. würden diese 128 bytes nicht wirklich fehlen und obendrein ist diese variante die schnellste. ausserdem hätten die trolle dann keinen stoff mehr für ihren fight, welcher code denn nun am frickligsten sei.

    char array[128];
    #define PLATZ_RESERVIEREN(p) (array[p]=1)
    #define PLATZ_FREIGEBEN(p) (array[p]=0)
    #define IST_PLATZ_RESERVIERT(p) (array[p]==1)
    

    🙂


Anmelden zum Antworten