Ich wünsche mir häufig, ich könnte so etwas in c tun:
val1 &= 0b00001111; //clear high nibble
val2 |= 0b01000000; //set bit 7
val3 &= ~0b00010000; //clear bit 5
Diese Syntax zu haben, scheint eine unglaublich nützliche Ergänzung zu C zu sein, ohne Nachteile, die mir einfallen, und es scheint eine natürliche Sache für eine Low-Level-Sprache zu sein, in der Bit-Twiddling ziemlich üblich ist.
Bearbeiten: Ich sehe einige andere großartige Alternativen, aber sie fallen alle auseinander, wenn es eine komplexere Maske gibt. Zum Beispiel, wenn reg ist ein Register, das E/A-Pins auf einem Mikrocontroller steuert, und ich möchte die Pins 2, 3 und 7 gleichzeitig hochsetzen, wenn ich schreiben könnte reg = 0x46; aber ich musste 10 Sekunden damit verbringen, darüber nachzudenken (und ich werde wahrscheinlich jedes Mal wieder 10 Sekunden verbringen müssen, wenn ich diesen Code lese, nachdem ich ihn ein oder zwei Tage lang nicht angesehen habe), oder ich könnte schreiben reg = (1 << 1) | (1 << 2) | (1 << 6); aber ich persönlich denke, dass das viel weniger klar ist, als einfach nur `reg = 0b01000110;’ zu schreiben. Ich kann jedoch zustimmen, dass es nicht weit über 8-Bit- oder vielleicht 16-Bit-Architekturen hinaus skaliert. Nicht, dass ich jemals eine 32-Bit-Maske erstellen musste.
es hat Hex, was meiner Meinung nach noch besser ist, wenn Sie 10 Minuten damit verbringen, ein Gefühl für die Beziehung zu bekommen
– vroomfondel
15. August 2013 um 1:00 Uhr
C hat “binäre” Literale, aber nur 2 davon: 0, 1. 😉
– chux – Wiedereinsetzung von Monica
15. August 2013 um 4:25 Uhr
Für das, was es wert ist, wird C++14 diese haben.
– Nemo
15. August 2013 um 5:19 Uhr
#define B00000000 0#define B00000001 1#define B00000010 2#define B00000011 3 … #define B10100100 0xA4 … evtl. mit Gips dazu unsigned char.
Das ist großartig, aber ich verwende GCC nicht 🙁 Weißt du, was nicht im Standard ist?
– Zeichnete
15. August 2013 um 1:08 Uhr
@Drew Siehe das Update. Mit anderen Worten, das Komitee glaubt, dass seine Verwendung durch Hex-Konstanten abgedeckt werden kann, denke ich.
– Yu Hao
15. August 2013 um 1:24 Uhr
Manchmal denke ich, dass die Leute, die Standards schreiben, nichts in der Sprache codieren, die sie standardisieren. Das, oder sie sind alle Teil desselben Nischen-Tech-Raums und können sich nicht vorstellen, dass irgendjemand die Sprache für etwas anderes verwendet als das, wofür er sie verwendet.
– Kurt E. Schneider
22. Februar um 2:33 Uhr
Jakob Pollack
Das hat gedrängt hexadezimal sein … hexadezimal. Das “… Die primäre Verwendung der hexadezimalen Notation ist eine benutzerfreundliche Darstellung von binär codierten Werten in der Computer- und Digitalelektronik …“. Es wäre wie folgt:
val1 |= 0xF;
val2 &= 0x40;
val3 |= ~0x10;
Hexadezimal:
Eine Hex-Ziffer kann ein Nibble darstellen (4 Bits oder ein halbes Oktal).
Zwei Hexadezimalziffern können ein Byte (8 Bit) darstellen.
Hex ist beim Skalieren auf größere Masken viel kompakter.
Mit etwas Übung wird die Konvertierung zwischen hexadezimal und binär viel natürlicher. Versuchen Sie, Ihre Umrechnungen von Hand aufzuschreiben und keinen Online-Bin/Hex-Notationskonverter zu verwenden – dann wird es in ein paar Tagen selbstverständlich (und dadurch schneller).
Beiseite: Obwohl binäre Literale kein C-Standard sind, ist es möglich, wenn Sie mit GCC kompilieren, binäre Literale zu verwenden, denen ‘0b’ oder ‘0B’ vorangestellt werden sollte. Siehe die offizielle Dokumentation hier Für weitere Informationen. Beispiel:
int b1 = 0b1001; // => 9
int b2 = 0B1001; // => 9
Ja, das ist es, was ich stattdessen immer mache, aber ich muss immer eine Menge Berechnungen in meinem machen, um mich daran zu erinnern, was binär was in hax ist. Vor allem wenn ich zB. Löschen Sie die niedrigsten 6 Bits. Und ich stimme zu, dass binäre Literale für 32-Bit-Plattformen lang werden würden, aber in diesem Fall können Sie sie einfach nicht verwenden.
– Zeichnete
15. August 2013 um 1:06 Uhr
Das Denken in Hexerei wird nach ein wenig Übung zur zweiten Natur. Hex hat auch den Vorteil, dass es einfacher zu lesen ist als binär.
– markgz
15. August 2013 um 1:08 Uhr
@Drew, ich verstehe deinen Standpunkt, da es für kleinere Masken visuell viel einfacher ist, darüber nachzudenken. Sobald Sie genug geübt haben, wird es ziemlich natürlich (wie alles im Leben kommt). Ich empfehle, alle Berechnungen von Hand durchzuführen und sich beim Erstellen von Masken mit einem Taschenrechner zu überprüfen, damit Sie besser werden und zwischen den beiden Notationen konvertieren können.
– Jakob Pollack
15. August 2013 um 1:09 Uhr
Wie viel Kopfrechnen braucht man wirklich, um sich den Binärwert vorzustellen, der durch eine Hexadezimalzahl dargestellt wird? Von allen Operationen/Berechnungen, die ein guter Programmierer im Kopf durchführen muss, ist diese meiner Meinung nach eine der einfachsten.
– Schleicher
15. August 2013 um 1:40 Uhr
Bitte ändern Sie in Aufzählungspunkt 1 “4 Bytes” in “4 Bits”. Ein Halbbyte besteht aus 4 Bits, nicht aus Bytes.
– Hans Dampf
6. Oktober 2015 um 11:40 Uhr
Nemo
Alle Ihre Beispiele können noch deutlicher geschrieben werden:
val1 &= (1 << 4) - 1; //clear high nibble
val2 |= (1 << 6); //set bit 6
val3 &=~(1 << 3); //clear bit 3
(Ich habe mir die Freiheit genommen, die Kommentare so festzulegen, dass sie von Null an zählen, wie es die Natur beabsichtigt hat.)
Ihr Compiler faltet diese Konstanten, sodass es keine Leistungseinbußen gibt, sie auf diese Weise zu schreiben. Und diese sind leichter zu lesen als die 0b... Versionen.
@Jerry Nun, das wird mich lehren, nach dem ersten Fehler nicht aufzuhören zu denken. Vielen Dank
– Nemo
15. August 2013 um 1:59 Uhr
Wenn wir Endianness berücksichtigen, ist (1 << 4) - 1 wirklich das gleiche wie 0xF ? … vielleicht nicht.
– Abraham Sánchez
1. September 2015 um 1:54 Uhr
@AbrahamSanchez: Ja, es ist auf allen Plattformen genau gleich. Arithmetische Operationen wie Linksverschiebung werden unabhängig von Endianness definiert. (Tatsächlich ist Endianness nicht einmal erkennbar, es sei denn, Sie setzen einen Zeiger oder verwenden eine Vereinigung.)
– Nemo
1. September 2015 um 3:47 Uhr
@Nemo oder ein Array, eine Struktur oder eine andere Variable. Solange Sie einen Hack wie den memcpy verwenden, ist alles möglich.
– yyny
2. März 2016 um 23:43 Uhr
@YoYoYonnY: Alle diese erfordern, dass Sie “einen Zeiger setzen oder eine Vereinigung verwenden”, wie ich sagte.
– Nemo
2. März 2016 um 23:51 Uhr
Ich denke, die Lesbarkeit ist ein Hauptanliegen. Obwohl auf niedriger Ebene, sind es Menschen, die Ihren Code lesen und pflegen, nicht Maschinen.
Können Sie leicht herausfinden, dass Sie sich vertippt haben? 0b1000000000000000000000000000000(0x40000000)wo du wirklich meinst 0b10000000000000000000000000000000(0x80000000) ?
“Zum Beispiel, wenn reg ein Register ist, das I/O-Pins auf einem Mikrocontroller steuert”
Ich kann nicht umhin zu denken, dass dies ein schlechtes Beispiel ist. Bits in Steuerregistern haben spezifische Funktionen (ebenso wie alle Geräte, die mit einzelnen IO-Bits verbunden sind).
Es wäre viel sinnvoller, symbolische Konstanten für Bitmuster in einer Header-Datei bereitzustellen, anstatt die Binärdatei innerhalb des Codes zu erarbeiten. Das Konvertieren von binär in hexadezimal oder oktal ist trivial, sich daran zu erinnern, was passiert, wenn Sie 01000110 in ein IO-Register schreiben, ist es nicht, insbesondere wenn Sie das Datenblatt oder den Schaltplan nicht zur Hand haben.
Sie sparen sich dann nicht nur die 10 Sekunden, um den Binärcode herauszufinden, sondern vielleicht auch die etwas längere Zeit, um herauszufinden, was er tut!
phip1611
Ich empfehle dafür C-Makros in C, um Compiler-Warnungen oder andere Probleme zu vermeiden. Anstelle von 0x verwende ich Ox (wie in “Ohio”).
es hat Hex, was meiner Meinung nach noch besser ist, wenn Sie 10 Minuten damit verbringen, ein Gefühl für die Beziehung zu bekommen
– vroomfondel
15. August 2013 um 1:00 Uhr
C hat “binäre” Literale, aber nur 2 davon: 0, 1. 😉
– chux – Wiedereinsetzung von Monica
15. August 2013 um 4:25 Uhr
Für das, was es wert ist, wird C++14 diese haben.
– Nemo
15. August 2013 um 5:19 Uhr
#define B00000000 0
#define B00000001 1
#define B00000010 2
#define B00000011 3
…#define B10100100 0xA4
… evtl. mit Gips dazuunsigned char
.– pmg
25. Juli 2017 um 18:52 Uhr
@AnT: genauer gesagt,
0
ist ein Oktalkonstante– chqrlie
25. August 2018 um 8:24 Uhr