Подтвердить что ты не робот

Написание двоичной числовой системы в коде C

Как мы используем префикс 0x для шестнадцатеричных чисел и o для восьмеричных, есть ли что-нибудь, что можно сделать для двоичных чисел?

Я попробовал суффикс b, но GCC не разрешил его.

Ошибка: недопустимый суффикс "b" для целочисленной константы

Возможно ли это?

4b9b3361

Ответ 1

Стандарт C не определяет двоичные константы. Там расширение GNU (я считаю) хотя (среди популярных компиляторов, clang также его адаптирует): префикс 0b:

int foo = 0b1010;

Если вы хотите придерживаться стандартного C, тогда есть опция: вы можете комбинировать макрос и функцию для создания почти читаемой функции "двоичной константы":

#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 foo = B(1010);

Если вы включите мощные оптимизаторы компилятора, компилятор, скорее всего, полностью устранит вызов функции (постоянное сгибание) или по крайней мере встроит его, поэтому это даже не будет проблемой производительности.

Доказательство:

Следующий код:

#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;
}

был скомпилирован с использованием clang -o baz.S baz.c -Wall -O3 -S, и он создал следующую сборку:

    .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

Итак, clang полностью исключил вызов функции и заменил его возвращаемое значение на 101. Аккуратно, да?

Ответ 2

Префикс вы буквально с 0b, как в

int i = 0b11111111;

Смотрите здесь.

Ответ 3

Используйте BOOST_BINARY (да, вы можете использовать его на C).

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

Этот макрос расширяется до восьмеричного литерала во время предварительной обработки.