Warum hat C keine binären Literale?

Lesezeit: 7 Minuten

Drews Benutzeravatar
Zeichnete

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.

    – pmg

    25. Juli 2017 um 18:52 Uhr


  • @AnT: genauer gesagt, 0 ist ein Oktalkonstante

    – chqrlie

    25. August 2018 um 8:24 Uhr

Benutzeravatar von Yu Hao
Yu Hao

Entsprechend Begründung für International Standard – Programmiersprachen C §6.4.4.1 Ganzzahlige Konstanten

Ein Vorschlag, binäre Konstanten hinzuzufügen, wurde aufgrund fehlender Präzedenzfälle und unzureichender Nützlichkeit abgelehnt.

Es ist nicht in Standard-C, aber GCC unterstützt es als Erweiterung mit dem Präfix by 0b oder 0B:

 i = 0b101010;

Sehen hier für Details.

  • 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

Benutzeravatar von Jacob Pollack
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:

  1. Eine Hex-Ziffer kann ein Nibble darstellen (4 Bits oder ein halbes Oktal).
  2. Zwei Hexadezimalziffern können ein Byte (8 Bit) darstellen.
  3. 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

Benutzeravatar von Nemo
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!

Benutzeravatar von phip1611
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”).

#define Ob00000001 1
#define Ob10000000 (1 << (8-1))
#define Ob00001111 15
#define Ob11110000_8 (Ob00001111 << (8 - 4))
#define Ob11110000_16 (Ob00001111 << (16 - 4))
#define Ob11110000_32 (((uint32_t) Ob00001111) << (32 - 4))
#define Ob11110000_64 (((uint64_t) Ob00001111) << (64 - 4))
#define Ox0F Ob00001111
#define OxF0 Ob11110000_8
#define OxF000 Ob11110000_16
#define OxF0000000 Ob11110000_32
#define OxF000000000000000 Ob11110000_64

int main() {
    #define Ob00001110 14
    // bitwise operations work
    if (Ob00001110 == (Ob00001111 & ~Ob00000001)) {
        printf("true\n");
    }
}

Mein Ansatz war:

/* binmacro.h */

#define BX_0000 0
#define BX_0001 1
#define BX_0010 2
#define BX_0011 3
#define BX_0100 4
#define BX_0101 5
#define BX_0110 6
#define BX_0111 7
#define BX_1000 8
#define BX_1001 9
#define BX_1010 A
#define BX_1011 B
#define BX_1100 C
#define BX_1101 D
#define BX_1110 E
#define BX_1111 F

#define BIN_A(x) BX_ ## x

#define BIN_B(x,y) 0x ## x ## y
#define BIN_C(x,y) BIN_B(x,y)

#define BIN_B4(x,y,z,t) 0x ## x ## y ## z ## t
#define BIN_C4(x,y,z,t) BIN_B4(x,y,z,t)

#define BIN(x,y) BIN_C(BIN_A(x),BIN_A(y))
#define BIN4(x,y,z,t) BIN_C4(BIN_A(x),BIN_A(y),BIN_A(z),BIN_A

/*---- test ... ---*/

BIN(1101,0100)

BIN4(1101,0010,1100,0101)

Welche Vorprozesse zu …

$  cpp binmacro.h
0xD4

0xD2C5

1408600cookie-checkWarum hat C keine binären Literale?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy