Bits genau setzen ?



  • 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)
    

    🙂



  • (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.

    1/8 = 0,2 ? 2/8 = 0...8 ?? die komplette Zeile kann ich nicht nachvollziehen, kannst du das nochmals erläutern?

    Wenn Nr der zu reservierende Platz ist Minus die 1 da 127stes bit Platz 128 ist... angenommen platzNr = 17 --> 17-1 /8 (Bits) = 16 /8 = 2 das würde beudeten p[2] also würde das 3 bit z.b. gesetzt, doch die platzNr war 17 sprich das 17. bit müsste gesetzt werden nicht das 3 ?

    @troll-fan dannke, aber das hatte mit bitmasken ja nichts mehr zu tun daher komme ich von der idee weg, geht ja auch um dern lerneffekt etc...



  • 1/8 = 0 KOMMA 2/8 = 0 KOMMA ... usw



  • Pelle1 schrieb:

    das würde beudeten p[2] also würde das 3 bit z.b. gesetzt, doch die platzNr war 17 sprich das 17. bit müsste gesetzt werden nicht das 3 ?

    nö, mit p[0], p[1], p[2] adressierst du jeweils 8 bit, wenn es char arrays sind:

    11111111 p[0]
    11111111 p[1]
    11111111 p[2]
    .
    .
    .
    usw

    die bitmaske legt dann fest, welches bit von den 8 aus/eingeschaltet wird
    🙂



  • troll-fan schrieb:

    @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)
    

    🙂

    bist du ein makro troll ?



  • kenner der trolle schrieb:

    bist du ein makro troll ?

    ja! und?
    🙂



  • Tim schrieb:

    Du findest >>3 so lesbar wie /8? Und &3 so lesbar wie %4?

    wollte ja nur sagen um das "/8" und "%8" kommt man nich rum, ich würde, sofern man keinen nachteil bis auf die bessere lesbarkeit in kauf nehmen muss (und normalerweise muss man das wirklich nicht, denn moderne compiler machen da keinen unterschied mehr) die normalen rechenoperatoren verwenden, also nein.

    Tim schrieb:

    Du findest a und p sind gute Bezeichner?

    naja, die sind vielleicht etwas unglücklich gewählt worden, aber sowas kann man bei einer funktion auch schreiben 😉

    Tim schrieb:

    Und die wichtigste Frage: Was denkst du ist für Anfänger besser geeignet?

    Ohja, da muss ich dir recht geben, nur wer mit bits hantieren will, kommt am binären zahlensystem nicht vorbei - dazu gehören auch, die operatoren.



  • warum nennst du dich scheise
    ?



  • unsigned int iLagerplaetze[4]; // 128 Bits
    int temp;
    

    Verständnisfrage:

    Habe ich das richtig verstanden?

    Aus einem Buch:

    unsigned zahl = 5, ergebnis;
    ergebnis = zahl << 3; // 40 = 5 * 23
    ergebnis = zahl >> 1; // 2 = 5 /21
    

    23 und 21 etc.. wie kommt man auf die werte ??? ok der autor hat auch das int vergessen, denke 23/21 sind auch einfach Schreibfähler...

    Was nervt ist, dass in der Literatur immer davon gesprochen wird, das bestimmte Bits gelöscht werden durch eine so genannte Bitmaske z.B. 0x7F doch ich habe 128 Möglichkeiten, da kann ich doch net alle Bitmasken vorfestlegen??? zudem muss das ganze shit auch ohne bitmasken gehen, dass es nicht in unserem unterricht behandelt wurde. Jetzt habe ich 3 Bücher gekauft und alle haben eine scheiss kurze Einführung und dämliche Beispiele mit der hexadezimalen schreibweise bzw. den bitmasken, muss doch auch ohne gehen???

    Frage:

    zitat wikipedia:"ergebnis = 5 % 2; // ergebnis hat den Wert 1"

    sprich 5/2 = 2 rest 1 also bleibt eins übrig? wenn ja warum ergibt 7 % 2 die Zahl 1 weil 2 genau 3 mal in 7 geht uns 1 übrig bleibt?

    was würde dann 2 % 7 ergeben? 0 ?



  • Hi Leude,

    kämpfe seit ner Stunde mit meinem Linker herum, bin deswegen wohl nimmer aktuell, aber vielleicht macht's die Kürze aus:

    char lkw[16];
    
    // -------------------
    void belege(char platz)
    {
    	unsigned int row, column;
    	platz--;					// Input nicht von 0 bis 127, sondern von 1 bis 128
    	row = platz >> 3;			// entspricht Div 8 -> Byteplatz
    	column = platz % 8;			// modulo 8 -> Bitplatz
    	lkw[row] |= (1 << column);	// Hineingeodert
    }
    

    Einfach mal mit nem Debugger anschauen, vielleicht rieseln dann die Groschen - ich konnte es jetzt nicht, sollte aber stimmen.



  • C/C++ Code:
    unsigned zahl = 5, ergebnis;
    ergebnis = zahl << 3; // 40 = 5 * 23
    ergebnis = zahl >> 1; // 2 = 5 /21

    23 und 21 etc.. wie kommt man auf die werte ??? ok der autor hat auch das int vergessen, denke 23/21 sind auch einfach Schreibfähler...

    Mit 23 und 21 ist wohl 2^3 (2 hoch 3) und 2^1 (2 hoch 1) gemeint.

    Und 2%7 gibt 2, 2%8 und 2%5 und 2%10 übrigens auch.



  • keyword: modulo operator bit shift operator

    operand1 % operand2 immer = 0 wenn beide werte gleich sind;

    operand1 % operand2 immer wert von operand1 wenn operand2 > operand1;

    operand1 % operand2 ist eine division op1 / op2, dabei wird geprüft wie oft op2 in

    op1 passt z.B. 55 % 6 , hier geht die 6 genau 9 mal rein denn 6 * 9 = 54. 10 mal würde die 6 nicht in 55 gehen denn 10 * 6 ergibt 60, demnach bleibt ein Restwert von 1 denn 55 - 54 = 1

    Juchuuu den modulo hab ich jetzt kapiert durch probieren, als 3 C Bücher liegen hier rum und bei allen gabs nix zu verstehn tststs... ich sollte Autor für C Anfänger werden 😃

    void platz_reservieren( int Nr, unsigned int* p )
    
    {   p[(Nr-1)/32] |= (1<<( (Nr-1)%32 ));   }
    

    selbst die Zeile habe ich jetzt endlich verstanden.

    Wenn man sich obige Zeile anschaut muss man sich der Vorrangigkeit der Operatoren bewußt sein, sonst kann alles rauskommen nur net das was richtig ist:

    1. ()
    2. %
    3. -
    4. <<
    

    Damit wird erstmal festgelegt, in welcher Reihenfolge obige Frickelei abgearbeitet wird.

    Beispiel: Lagerplatz zu reservieren wäre 128:

    1. Zuerst (128-1) = 127 // "-" kommt zwar nach % doch "-" ist in der Klammer...
    2. 127 % 32 = 3 mal gehts rein Rest = 31
    3. Dieser Rest 31 bedeutet, dass dass 1 Bit der variablen "Nr" 31 mal nach links geshiftet wird: 1 << 31 wäre das. Rechts von dem 32. bit dann wird alles mit 0 aufgefüllt so: 10000000 00000000 00000000 00000000 <--- Variable "Nr" nach der kompletten rechtsseitigen Berechnung: Nun muss nur noch linksseitige Berechnung vorgenommen werden und da habe ich noch ein kleines Problem:

    p[(Nr-1)/32]
    

    gleiches Beispiel: (128-1)= 127, 127/32 = 3,96

    Wie kann ich einen index von 3,96 in dem Array p[3,96] ansprechen? Ich nehme an es liegt daran, dass die Nachkommastelle(n) bei einer int division einfach abgeschnitten werden. Würde man die Nr-1 nicht machen hätte ich 128/32 wodurch ich den index 4 ansprechen würde was nicht reserviert wurde sprich index out of bounds exception 😃 das ganze mit "|" verknüpft und das Bit 1 wird in p[3] gesetzt! Goil wa ich habs 😮 😮 😃 Danke an frickler mittlerweile mag ich deine Methode weil sie doch sehr ausgeklügelt ist, für einen n00b zwar hartes brot doch irgendwann fällt bei jedem der Groschen :p 👍 👍



  • so wie x +=1 schreiben kann für x = x +1 wie mache ich dies für untenstehenden code?

    p[(Nr-1)/32] |= (1<<( (Nr-1)%32 ));
    

    Das kann ja nicht stimmen oder?

    p[(Nr-1)/32] = p[(Nr-1)/32] | (1<<( (Nr-1)%32 ));
    


  • Pelle schrieb:

    1. Zuerst (128-1) = 127 // "-" kommt zwar nach % doch "-" ist in der Klammer...
    2. 127 % 32 = 3 mal gehts rein Rest = 31
    3. Dieser Rest 31 bedeutet, dass dass 1 Bit der variablen "Nr" 31 mal nach links geshiftet wird: 1 << 31 wäre das. Rechts von dem 32. bit dann wird alles mit 0 aufgefüllt so: 10000000 00000000 00000000 00000000 <---

    Bis hierhin sieht's richtig aus.

    Variable "Nr" nach der kompletten rechtsseitigen Berechnung: Nun muss nur noch linksseitige Berechnung vorgenommen werden und da habe ich noch ein kleines Problem:

    p[(Nr-1)/32]
    

    gleiches Beispiel: (128-1)= 127, 127/32 = 3,96

    Wie kann ich einen index von 3,96 in dem Array p[3,96] ansprechen? Ich nehme an es liegt daran, dass die Nachkommastelle(n) bei einer int division einfach abgeschnitten werden.

    Richtig erkannt - wir reden hier von Ganzzahldivision und dabei werden nachkommastellen einfach weggelassen (127/32==3).

    Das "Nr-1" ist übrigens nötig, weil da jemand den Index von 1 an gezählt hat - ein erfahrener C-Programmierer hätte die Lagerplätze von 0 bis 127 nummeriert.

    Pelle schrieb:

    so wie x +=1 schreiben kann für x = x +1 wie mache ich dies für untenstehenden code?

    p[(Nr-1)/32] |= (1<<( (Nr-1)%32 ));
    

    Das kann ja nicht stimmen oder?

    p[(Nr-1)/32] = p[(Nr-1)/32] | (1<<( (Nr-1)%32 ));
    

    Klar stimmt das so, warum auch nicht?



  • Das kann ja nicht stimmen oder?

    p[(Nr-1)/32] = p[(Nr-1)/32] | (1<<( (Nr-1)%32 ));
    

    Klar stimmt das so, warum auch nicht? [/quote]

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

    das wäre dann auch richtig?

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


  • Wenn ich jetzt keinen Tippfehler übersehen habe, ja.


Anmelden zum Antworten