Bits genau setzen ?
-
Hallo,
der Benutzer kann eine Lagerplatznummer reservieren auf einem LKW-Anhänger. Jeder Anhänger hat 128 Lagerplätze zur Verfügung von 1 - 128. Ist ein Lagerplatz belegt = 1 , frei = 0
Nun frage ich mich, ob ich
1. ein Array mit 128 int werten reservieren soll z.B.
int iArrayLagerplatz[128]
oder
2. ein Array mit 4 int Werten
int iArrayLagerplatz[4]
Ersteres wäre zwar geschickt da die Lagerplatznummer dem Index des Arrays entspräche doch dann müsste ich auch alle 32 bits von der einer Array variablen setzen, testen, löschen -> Ressourcenverschwendung.
Letzeres birgt das Problem dass ich nicht weiß, wenn der Benutzer z.B. Lagerplatz 73 eingibt, wie ich genau das Bit an an der Position 73 auf 1 setze , denn die Zahl 73 ist binär dargestellt nicht:
Array index [0]: 00000000 00000000 00000000 00000000 = 32 bit Array index [1]: 00000000 00000000 00000000 00000000 = 32 bit kumuliert: 64 bit Array index [2]: 00000000 10000000 00000000 00000000 = 32 bit wobei das 73 bit
gesetzt ist.
Wie kann ich also genau das Bit 73 setzen sodass die restlichen bits unangetastet bleiben, denn die dezimahlzahl 73 ist binär ja
*rechne nach* 01001001 (64+8+1) doch 01001001 entspricht halt nicht obigem bit 73...
-
Das kannst du mit Bitoperatoren erreichen.
Mit ODER | kannst du Bits setzten mit UND & löschen und abfragen
ob sie gesetzt sind. Die entsprechende Bitmaske erhälts
du indem du eine 1 mittels Bitverschiebung << an die richtige
Position schiebst.
http://www.willemer.de/informatik/cpp/sysprog.htm
-
Storm.Xapek.de schrieb:
Das kannst du mit Bitoperatoren erreichen.
Mit ODER | kannst du Bits setzten mit UND & löschen und abfragen
ob sie gesetzt sind. Die entsprechende Bitmaske erhälts
du indem du eine 1 mittels Bitverschiebung << an die richtige
Position schiebst.
http://www.willemer.de/informatik/cpp/sysprog.htmhttp://www.arndt-bruenner.de/mathe/scripts/Zahlensysteme.htm
habe mal meine zahl 73 von dezimal ins binär umrechnen lassen, dabei kommt mit obigem link das raus: 10001001 ich bekomme was anderes raus...
das ist die Erklärung:
Die Dezimalzahl 73 wird ins 2er-System umgewandelt Gehe nach folgendem Verfahren vor: (1) Teile die Zahl mit Rest durch 2. (2) Der Divisionsrest ist die nächste Ziffer (von rechts nach links). (3) Falls der (ganzzahlige) Quotient = 0 ist, bist du fertig, andernfalls nimm den (ganzzahligen) Quotienten als neue Zahl und wiederhole ab (1). 73 : 2 = 36 Rest: 1 36 : 2 = 18 Rest: 0 18 : 2 = 9 Rest: 0 9 : 2 = 4 Rest: 1 4 : 2 = 2 Rest: 0 2 : 2 = 1 Rest: 0 1 : 2 = 0 Rest: 1
Wieso ist deren Byte 7 Bit groß ?? ok gebe ich
die zahl 128 ein sinds 8 bit doch die erklärungen sind gemäß was ich lernte völlig falsch?
Wenn ich eine int variable nicht initialisiere, dann hat doch jedes Bit 0 oder sprich 32 nullen?
Nächste Frage:
unsigned Char (Bit 0-7) testByte = 0x01 / binär: 0000 0001
analog zu unsigned int (Bit 0-31) test4Byte = 0x01 / binär stimmt das? ->
00000000 00000000 00000000 00000001 ? Wo finde ich denn was über denn 0x01 "operator" oder die schreibweise etc... in meinem buch steht da nichts weiteres...
Kann mir jemand die Funktion erklären bzw. deren 3 variablen oder ich versuchs mal teilweise...:
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 }
Doch welche Bedeutung hat "wert" , die variable die verändert wird letztendlich ?!?! Und welche Bedeutung hat die variable "bit" ist das die benutzereingabe z.B. platz 128 wäre also bit = 128 ? sprich bei test_val << 128 würde das 128igste Bit gesetzt werden ?
-
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))))
(ungetestet)
wobei 'a' das array aus 8 bytes (oder ein pointer darauf) und 'p' die bitnummer ist.
-
@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?