Binäres Zahlensystem in C-Code schreiben [duplicate]

Lesezeit: 4 Minuten

Benutzeravatar von cipher
Chiffre

Wie wir verwenden 0x Präfix für Hexadezimalzahlen und 0 Gibt es für Oktalzahlen irgendetwas, das für Binärzahlen getan werden kann?

Ich versuchte die b Suffix, aber die GCC ließ es nicht zu.

Fehler: Ungültiges Suffix „b“ auf ganzzahliger Konstante

Ist es möglich?

  • Binäre Literale gibt es in C nicht. Am nächsten kommen Sie hexadezimal, da sie dem binären Bitmuster genau folgen.

    – Irgendein Programmierer-Typ

    27. Februar 2013 um 14:09 Uhr


  • Hex zu Binär ist wirklich einfach zu konvertieren.

    Benutzer1944441

    27. Februar 2013 um 14:09 Uhr

Standard-C definiert keine binären Konstanten. Es gibt jedoch eine GNU-C-Erweiterung (unter den beliebten Compilern passt clang sie auch an): the 0b oder 0B Präfixe:

int foo = 0b1010;

Wenn Sie bei Standard-C bleiben möchten, gibt es eine Option: Sie können ein Makro und eine Funktion kombinieren, um eine zu erstellen fast lesbare “Binärkonstante”-Funktion:

#define B(x) S_to_binary_(#x)

static inline unsigned long long S_to_binary_(const char *s)
{
        unsigned long long i = 0;
        while (*s) {
                i <<= 1;
                i += *s++ - '0';
        }
        return i;
}

Und dann kannst du es so verwenden:

int foo = B(1010);

Wenn Sie starke Compiler-Optimierungen aktivieren, wird der Compiler den Funktionsaufruf höchstwahrscheinlich vollständig eliminieren (konstante Faltung) oder ihn zumindest einbetten, sodass dies nicht einmal ein Leistungsproblem darstellt.

Nachweisen:

Der folgende Code:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>


#define B(x) S_to_binary_(#x)

static inline unsigned long long S_to_binary_(const char *s)
{
    unsigned long long i = 0;
    while (*s) {
        i <<= 1;
        i += *s++ - '0';
    }
    return i;
}

int main()
{
    int foo = B(001100101);

    printf("%d\n", foo);

    return 0;
}

wurde kompiliert mit clang -o baz.S baz.c -Wall -O3 -Sund es wurde die folgende Assembly erstellt:

    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    leaq    L_.str1(%rip), %rdi
    movl    $101, %esi               ## <= This line!
    xorb    %al, %al
    callq   _printf
    xorl    %eax, %eax
    popq    %rbp
    ret
    .cfi_endproc

    .section    __TEXT,__cstring,cstring_literals
L_.str1:                                ## @.str1
    .asciz   "%d\n"


.subsections_via_symbols

So clang den Aufruf der Funktion vollständig eliminiert und ihren Rückgabewert durch ersetzt 101. Ordentlich, oder?

  • @Lundin Häh? Der Punkt ist Lesbarkeit und Besitz binäre Literale.

    Benutzer529758

    27. Februar 2013 um 14:41 Uhr


  • @Lundin Habe ich dagegen argumentiert? OP fragte “wie ist das möglich”, und ich habe ihm gezeigt, wie. Zeit, mich in Ruhe zu lassen.

    Benutzer529758

    27. Februar 2013 um 14:47 Uhr

  • “Der Punkt ist die Lesbarkeit …” ist in der Tat ein Argument für binäre Literale.

    – Ludin

    27. Februar 2013 um 14:52 Uhr

  • @Lundin Es gibt viele Situationen, in denen viele Leute Binärzahlen lesbarer finden würden. Tatsächlich kommentieren viele Programmierer beim Definieren von Aufzählungen mit vielen Flags jede Konstante mit ihrem Binärwert in einem Kommentar. Und da C++ nun benutzerdefinierte Literale bereitstellt, implementieren viele Leute als Erstes eine Erweiterung für binäre Zahlenliterale.

    – Konrad Rudolf

    27. Februar 2013 um 16:24 Uhr


  • @Lundin – Nehmen Sie es von jemandem, der mit viel eingebetteter Hardware gearbeitet hat: Wir haben es oft mit Binärwerten zu tun, die nicht mit ihrem niedrigen Bit in Bit 0 beginnen, was den Datenbus der CPU betrifft. Natürlich sind Makros, die einen Wert annehmen und für Sie verschieben, in diesem Fall sehr nützlich und behandeln die Lesbarkeitsprobleme. Manchmal ist es schön, einfach ein binäres Literal angeben zu können. Als ich mich immer mehr an die eingebettete Programmierung gewöhnt habe, habe ich festgestellt, dass mein “Bedarf” an binären Literalen auf fast Null gesunken ist, aber am Anfang hätten sie so ausgesehen, als wären sie praktisch.

    – Telefontagger

    10. Juni 2013 um 15:40 Uhr

Stellen Sie Ihrem Literal ein Präfix voran 0b wie in

int i = 0b11111111;

Sehen hier.

  • Es ist jedoch eine Erweiterung, für die möglicherweise ein spezielles Flag erforderlich ist gcc es zu verstehen. Und natürlich nicht auf andere Compiler portierbar, die diese Erweiterung nicht unterstützen.

    – Irgendein Programmierer-Typ

    27. Februar 2013 um 14:11 Uhr


Verwenden BOOST_BINARY (Ja, Sie können es in C verwenden).

#include <boost/utility/binary.hpp>
...
int bin = BOOST_BINARY(110101);

Dieses Makro wird während der Vorverarbeitung zu einem oktalen Literal erweitert.

  • Ich erhalte eine Fehlermeldung, wenn ich BOOST_BINARY mit einer Variablen verwende: #include #include int main() { int bin; printf(“Geben Sie Ihre Binärzahl ein: “); scanf(“%i”, &bin); printf(“Der Dezimalwert ist %d”, BOOST_BINARY(bin)); 0 zurückgeben; } Der Fehler sagt Fehler: Makro “BOOST_DETAIL_SPLIT_AND_SWAP_PARAMS” erfordert 2 Argumente, aber nur 1 gegeben

    – John

    10. April 2019 um 21:32 Uhr


  • Es ist keine gute Idee, eine riesige Bibliothek wie Boost in die meisten Programme einzumischen. Vor allem, wenn sie klein und schnell zu kompilieren sind. Da C es bereits durch Erweiterung unterstützt, würde ich jedem raten, darum herum zu bauen und es mit Versionsmakros umzustellen.

    – Benutzer2262111

    6. Mai 2019 um 17:59 Uhr


1409020cookie-checkBinäres Zahlensystem in C-Code schreiben [duplicate]

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

Privacy policy