Могу ли я использовать двоичный литерал в C или C ++? - PullRequest
177 голосов
/ 10 апреля 2010

Мне нужно работать с двоичным числом.

Я пытался написать:

const x = 00010000;

Но это не сработало.

Я знаю, что могу использовать шестнадцатеричное число с тем же значением, что и 00010000, но я хочу знать, есть ли тип в C ++ для двоичных чисел, и если нет, есть ли другое решение для моего проблема?

Ответы [ 19 ]

7 голосов
/ 10 апреля 2010

Наименьшая единица измерения, с которой вы можете работать, - это байт (тип char). Вы можете работать с битами, используя битовые операторы.

Что касается целочисленных литералов, вы можете работать только с десятичными (основание 10), восьмеричными (основание 8) или шестнадцатеричными (основание 16) числами. В C и C ++ нет двоичных литералов (базы 2).

Восьмеричные числа имеют префикс 0, а шестнадцатеричные числа - 0x. Десятичные числа не имеют префикса.

В C ++ 0x вы сможете делать то, что вы хотите, кстати, с помощью пользовательских литералов .

4 голосов
/ 29 июня 2012

На основании некоторых других ответов, но этот отклонит программы с недопустимыми двоичными литералами. Ведущие нули необязательны.

template<bool> struct BinaryLiteralDigit;

template<> struct BinaryLiteralDigit<true> {
    static bool const value = true;
};

template<unsigned long long int OCT, unsigned long long int HEX>
struct BinaryLiteral {
    enum {
        value = (BinaryLiteralDigit<(OCT%8 < 2)>::value && BinaryLiteralDigit<(HEX >= 0)>::value
            ? (OCT%8) + (BinaryLiteral<OCT/8, 0>::value << 1)
            : -1)
    };
};

template<>
struct BinaryLiteral<0, 0> {
    enum {
        value = 0
    };
};

#define BINARY_LITERAL(n) BinaryLiteral<0##n##LU, 0x##n##LU>::value

Пример:

#define B BINARY_LITERAL

#define COMPILE_ERRORS 0

int main (int argc, char ** argv) {
    int _0s[] = { 0, B(0), B(00), B(000) };
    int _1s[] = { 1, B(1), B(01), B(001) };
    int _2s[] = { 2, B(10), B(010), B(0010) };
    int _3s[] = { 3, B(11), B(011), B(0011) };
    int _4s[] = { 4, B(100), B(0100), B(00100) };

    int neg8s[] = { -8, -B(1000) };

#if COMPILE_ERRORS
    int errors[] = { B(-1), B(2), B(9), B(1234567) };
#endif

    return 0;
}
2 голосов
/ 17 октября 2016

Я расширил хороший ответ, данный @ renato-chandelier, обеспечив поддержку:

  • _NIBBLE_(…) - 4 бита, 1 клев в качестве аргумента
  • _BYTE_(…) - 8 бит, 2 полубайта в качестве аргументов
  • _SLAB_(…) - 12 бит, 3 полубайта в качестве аргументов
  • _WORD_(…) - 16 битов, 4 полубайта в качестве аргументов
  • _QUINTIBBLE_(…) - 20 бит, 5 кусков в качестве аргументов
  • _DSLAB_(…) - 24 бита, 6 кусков в качестве аргументов
  • _SEPTIBBLE_(…) - 28 бит, 7 кусков в качестве аргументов
  • _DWORD_(…) - 32 бита, 8 полубайтов в качестве аргументов

На самом деле я не очень уверен в терминах «квинтибл» и «септибл». Если кто-нибудь знает какую-либо альтернативу, пожалуйста, дайте мне знать.

Вот макрос, переписанный:

#define __CAT__(A, B) A##B
#define _CAT_(A, B) __CAT__(A, B)

#define __HEX_0000 0
#define __HEX_0001 1
#define __HEX_0010 2
#define __HEX_0011 3
#define __HEX_0100 4
#define __HEX_0101 5
#define __HEX_0110 6
#define __HEX_0111 7
#define __HEX_1000 8
#define __HEX_1001 9
#define __HEX_1010 a
#define __HEX_1011 b
#define __HEX_1100 c
#define __HEX_1101 d
#define __HEX_1110 e
#define __HEX_1111 f

#define _NIBBLE_(N1) _CAT_(0x, _CAT_(__HEX_, N1))
#define _BYTE_(N1, N2) _CAT_(_NIBBLE_(N1), _CAT_(__HEX_, N2))
#define _SLAB_(N1, N2, N3) _CAT_(_BYTE_(N1, N2), _CAT_(__HEX_, N3))
#define _WORD_(N1, N2, N3, N4) _CAT_(_SLAB_(N1, N2, N3), _CAT_(__HEX_, N4))
#define _QUINTIBBLE_(N1, N2, N3, N4, N5) _CAT_(_WORD_(N1, N2, N3, N4), _CAT_(__HEX_, N5))
#define _DSLAB_(N1, N2, N3, N4, N5, N6) _CAT_(_QUINTIBBLE_(N1, N2, N3, N4, N5), _CAT_(__HEX_, N6))
#define _SEPTIBBLE_(N1, N2, N3, N4, N5, N6, N7) _CAT_(_DSLAB_(N1, N2, N3, N4, N5, N6), _CAT_(__HEX_, N7))
#define _DWORD_(N1, N2, N3, N4, N5, N6, N7, N8) _CAT_(_SEPTIBBLE_(N1, N2, N3, N4, N5, N6, N7), _CAT_(__HEX_, N8))

А вот пример использования Ренато:

char b = _BYTE_(0100, 0001); /* equivalent to b = 65; or b = 'A'; or b = 0x41; */
unsigned int w = _WORD_(1101, 1111, 0100, 0011); /* equivalent to w = 57155; or w = 0xdf43; */
unsigned long int dw = _DWORD_(1101, 1111, 0100, 0011, 1111, 1101, 0010, 1000); /* Equivalent to dw = 3745774888; or dw = 0xdf43fd28; */
2 голосов
/ 10 апреля 2010

«Тип» двоичного числа совпадает с любым десятичным, шестнадцатеричным или восьмеричным числом: int (или даже символ, короткий, длинный длинный).

Когда вы назначаете константу, вы не можете назначить ее с 11011011 (любопытно и к сожалению), но вы можете использовать шестнадцатеричное. Гекс немного легче мысленно перевести. Разбить на кусочки (4 бита) и перевести на символ в [0-9a-f].

2 голосов
/ 18 июля 2014

Вы также можете использовать встроенную сборку следующим образом:

int i;

__asm {
    mov eax, 00000000000000000000000000000000b
    mov i,   eax
}

std::cout << i;

Хорошо, это может быть несколько излишним, но это работает:)

2 голосов
/ 02 июня 2014

Вы можете использовать битовый набор

bitset<8> b(string("00010000"));
int i = (int)(bs.to_ulong());
cout<<i;
0 голосов
/ 29 июня 2015

Вы можете попробовать:

bool i[8] = {0,0,1,1,0,1,0,1}
0 голосов
/ 04 марта 2015

Просто используйте стандартную библиотеку в C ++:

#include <bitset>

Вам нужна переменная типа std::bitset:

std::bitset<8ul> x;
x = std::bitset<8>(10);
for (int i = x.size() - 1; i >= 0; i--) {
      std::cout << x[i];
}

В этом примере я хранил двоичный код 10 в x.

8ul определяет размер ваших битов, поэтому 7ul означает семь бит и т. Д.

0 голосов
/ 10 апреля 2010

C ++ предоставляет стандартный шаблон с именем bitset.Попробуйте, если хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...