Posso usar um literal binário em C ou C ++?

Eu preciso trabalhar com um número binário.

Eu tentei escrever:

const x = 00010000; 

Mas não funcionou.

Eu sei que eu posso usar um número hexadecimal que tem o mesmo valor que 00010000 , mas eu quero saber se há um tipo em C ++ para números binários e se não houver, há outra solução para o meu problema?

Você pode usar BOOST_BINARY enquanto aguarda o C ++ 0x. 🙂 BOOST_BINARY indiscutivelmente tem uma vantagem sobre a implementação do modelo, na medida em que ele pode ser usado em programas C também (é 100% orientado para o pré-processador).

ATUALIZAR

Para fazer o inverso (ou seja, imprimir um número em formato binário), você pode usar a function itoa não portátil ou implementar a sua própria function .

Infelizmente você não pode fazer a formatação da base 2 com streams STL (já que o setbase só irá honrar as bases 8, 10 e 16), mas você pode usar uma versão std::string do itoa ou (o mais conciso, mas marginalmente menos eficiente) std::bitset

(Obrigado Roger pela dica bitset !)

 #include  #include  #include  #include  #include  #include  using namespace std; int main() { unsigned short b = BOOST_BINARY( 10010 ); char buf[sizeof(b)*8+1]; printf("hex: %04x, dec: %u, oct: %06o, bin: %16s\n", b, b, b, itoa(b, buf, 2)); cout << setfill('0') << "hex: " << hex << setw(4) << b << ", " << "dec: " << dec << b << ", " << "oct: " << oct << setw(6) << b << ", " << "bin: " << bitset< 16 >(b) << endl; return 0; } 

produz:

 hex: 0012, dec: 18, oct: 000022, bin: 10010 hex: 0012, dec: 18, oct: 000022, bin: 0000000000010010 

Leia também The String Formatters, de Herb Sutter, de Manor Farm, para uma discussão interessante.

Se você estiver usando o GCC, então você pode usar uma extensão do GCC (que está incluída no padrão C ++ 14 ) para isso:

 int x = 0b00010000; 
 template struct bin { enum { value = (N%10)+2*bin::value }; } ; template<> struct bin<0> { enum { value = 0 }; } ; // ... std::cout << bin<1000>::value << '\n'; 

O dígito mais à esquerda do literal ainda tem que ser 1, mas mesmo assim.

Você pode usar literais binários. Eles são padronizados em C ++ 14. Por exemplo,

 int x = 0b11000; 

Suporte no GCC

O suporte no GCC começou no GCC 4.3 (consulte https://gcc.gnu.org/gcc-4.3/changes.html ) como extensões da família da linguagem C (consulte https://gcc.gnu.org/onlinedocs/gcc/ C-Extensions.html # C-Extensions ), mas desde o GCC 4.9 agora é reconhecido como um recurso do C ++ 14 ou uma extensão (veja Diferença entre os literais binários do GCC e os do C ++ 14? )

Suporte no Visual Studio

Suporte no Visual Studio iniciado no Visual Studio 2015 Preview (consulte https://www.visualstudio.com/news/vs2015-preview-vs#C++ ).

Alguns compiladores (geralmente os de microcontroladores ) têm um recurso especial implementado dentro do reconhecimento de números binários literais pelo prefixo “0b …” precedendo o número, embora a maioria dos compiladores (padrões C / C ++) não possuam tal recurso e se ele é o caso, aqui é minha solução alternativa:

 #define B_0000 0 #define B_0001 1 #define B_0010 2 #define B_0011 3 #define B_0100 4 #define B_0101 5 #define B_0110 6 #define B_0111 7 #define B_1000 8 #define B_1001 9 #define B_1010 a #define B_1011 b #define B_1100 c #define B_1101 d #define B_1110 e #define B_1111 f #define _B2H(bits) B_##bits #define B2H(bits) _B2H(bits) #define _HEX(n) 0x##n #define HEX(n) _HEX(n) #define _CCAT(a,b) a##b #define CCAT(a,b) _CCAT(a,b) #define BYTE(a,b) HEX( CCAT(B2H(a),B2H(b)) ) #define WORD(a,b,c,d) HEX( CCAT(CCAT(B2H(a),B2H(b)),CCAT(B2H(c),B2H(d))) ) #define DWORD(a,b,c,d,e,f,g,h) HEX( CCAT(CCAT(CCAT(B2H(a),B2H(b)),CCAT(B2H(c),B2H(d))),CCAT(CCAT(B2H(e),B2H(f)),CCAT(B2H(g),B2H(h)))) ) // Using example 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; 

Desvantagens (não são tão grandes):

  • Os números binários devem ser agrupados 4 por 4;
  • Os literais binários devem ser apenas números inteiros sem sinal;

Vantagens :

  • Total de pré-processador, não spending processor time em operações inúteis ( like "?.. :..", "<<", "+" ) para o programa executável (pode ser executado centenas de vezes na aplicação final);
  • Ele funciona "mainly in C" compiladores "mainly in C" e em C ++ (a template+enum solution works only in C++ compilers );
  • Ele tem apenas a limitação de "longitude" para expressar valores "constantes literais". Haveria uma limitação de longitude antecipada (geralmente 8 bits: 0-255) se alguém tivesse expressado valores constantes analisando a resolução de "enum solution" (usually 255 = reach enum definition limit) , diferentemente, "literal constante" limitações, no o compilador permite números maiores;
  • Algumas outras soluções exigem um número exagerado de definições constantes (muitas definem em minha opinião), incluindo several header files longos ou several header files (na maioria dos casos não são facilmente legíveis e compreensíveis, e tornam o projeto desnecessariamente confuso e extenso, assim usando "BOOST_BINARY()" );
  • Simplicidade da solução: facilmente legível, compreensível e ajustável para outros casos (pode ser estendido para o agrupamento 8 por 8 também);

Este tópico pode ajudar.

 /* Helper macros */ #define HEX__(n) 0x##n##LU #define B8__(x) ((x&0x0000000FLU)?1:0) \ +((x&0x000000F0LU)?2:0) \ +((x&0x00000F00LU)?4:0) \ +((x&0x0000F000LU)?8:0) \ +((x&0x000F0000LU)?16:0) \ +((x&0x00F00000LU)?32:0) \ +((x&0x0F000000LU)?64:0) \ +((x&0xF0000000LU)?128:0) /* User macros */ #define B8(d) ((unsigned char)B8__(HEX__(d))) #define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) \ + B8(dlsb)) #define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) \ + ((unsigned long)B8(db2)<<16) \ + ((unsigned long)B8(db3)<<8) \ + B8(dlsb)) #include  int main(void) { // 261, evaluated at compile-time unsigned const number = B16(00000001,00000101); printf("%d \n", number); return 0; } 

Funciona! (Todos os créditos vão para Tom Torfs.)

Como já foi respondido, os padrões C não têm como escrever diretamente os números binários. Existem extensões de compilador, no entanto, e aparentemente o C ++ 14 inclui o prefixo 0b para binário. (Observe que essa resposta foi originalmente publicada em 2010.)

Uma solução popular é include um arquivo de header com macros auxiliares . Uma opção fácil é também gerar um arquivo que inclua definições de macro para todos os padrões de 8 bits, por exemplo:

 #define B00000000 0 #define B00000001 1 #define B00000010 2 … 

Isso resulta em apenas 256 #define s e, se forem necessárias constantes binárias maiores que 8 bits, essas definições podem ser combinadas com turnos e ORs, possivelmente com macros auxiliares (por exemplo, BIN16(B00000001,B00001010) ). (Ter macros individuais para cada valor de 16 bits, e muito menos de 32 bits, não é plausível.)

É claro que a desvantagem é que essa syntax exige a gravação de todos os zeros à esquerda, mas isso também pode torná-la mais clara para usos como a configuração de sinalizadores de bit e o conteúdo de registradores de hardware. Para uma macro semelhante a uma function, resultando em uma syntax sem essa propriedade, consulte bithacks.h vinculado acima.

C não possui notação nativa para números binários puros. Sua melhor aposta aqui seria octal (por exemplo, 07777 ) de hexadecimal (por exemplo, 0xfff ).

A mentalidade de engenharia excessiva do C ++ já é bem explicada nas outras respostas aqui. Aqui está minha tentativa de fazer isso com uma mentalidade C, keep-it-simple-ffs:

 unsigned char x = 0xF; // binary: 00001111 

Você pode usar a function encontrada nesta pergunta para obter até 22 bits em C ++. Aqui está o código do link, adequadamente editado:

 template< unsigned long long N > struct binary { enum { value = (N % 8) + 2 * binary< N / 8 > :: value } ; }; template<> struct binary< 0 > { enum { value = 0 } ; }; 

Então você pode fazer algo como binary<0101011011>::value .

A menor unidade com a qual você pode trabalhar é um byte (que é do tipo char ). Você pode trabalhar com bits usando operadores bit a bit.

Quanto aos literais inteiros, você só pode trabalhar com números decimais (base 10), octais (base 8) ou hexadecimais (base 16). Não há literais binários (base 2) em C nem em C ++.

Os números octais são prefixados com 0 e os números hexadecimais são prefixados com 0x . Números decimais não têm prefixo.

Em C ++ 0x, você poderá fazer o que quiser, por meio de literais definidos pelo usuário .

Baseado em algumas outras respostas, mas esta rejeitará programas com literais binários ilegais. Zeros à esquerda são opcionais.

 template struct BinaryLiteralDigit; template<> struct BinaryLiteralDigit { static bool const value = true; }; template struct BinaryLiteral { enum { value = (BinaryLiteralDigit<(OCT%8 < 2)>::value && BinaryLiteralDigit<(HEX >= 0)>::value ? (OCT%8) + (BinaryLiteral::value << 1) : -1) }; }; template<> struct BinaryLiteral<0, 0> { enum { value = 0 }; }; #define BINARY_LITERAL(n) BinaryLiteral<0##n##LU, 0x##n##LU>::value 

Exemplo:

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

O “tipo” de um número binário é o mesmo que qualquer número decimal, hexadecimal ou octal: int (ou mesmo char, short, long long).

Quando você atribui uma constante, você não pode atribuí-la com 11011011 (curiosamente e infelizmente), mas você pode usar hexadecimal. Hex é um pouco mais fácil de traduzir mentalmente. Chunk em nibbles (4 bits) e traduza para um caractere em [0-9a-f].

Você também pode usar a assembly inline como esta:

 int i; __asm { mov eax, 00000000000000000000000000000000b mov i, eax } std::cout << i; 

Ok, pode ser um pouco exagerado, mas funciona 🙂

Você pode usar um bitset

 bitset<8> b(string("00010000")); int i = (int)(bs.to_ulong()); cout< 

Eu estendi a boa resposta dada por @ renato-candelabro, garantindo o apoio de:

  • _NIBBLE_(…) – 4 bits, 1 nibble como argumento
  • _BYTE_(…) – 8 bits, 2 nibbles como argumentos
  • _SLAB_(…) – 12 bits, 3 nibbles como argumentos
  • _WORD_(…) – 16 bits, 4 nibbles como argumentos
  • _QUINTIBBLE_(…) – 20 bits, 5 nibbles como argumentos
  • _DSLAB_(…) – 24 bits, 6 nibbles como argumentos
  • _SEPTIBBLE_(…) – 28 bits, 7 nibbles como argumentos
  • _DWORD_(…) – 32 bits, 8 nibbles como argumentos

Na verdade, não tenho tanta certeza sobre os termos “quintibble” e “septibble”. Se alguém souber de alguma alternativa, por favor me avise.

Aqui está a macro reescrita:

 #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)) 

E aqui está o exemplo de Renato:

 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; */ 

Apenas use a biblioteca padrão em C ++:

 #include  

Você precisa de uma variável do tipo std::bitset :

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

Neste exemplo, armazenei o binário de 10 em x.

8ul define o tamanho de seus bits, então 7ul significa sete bits e assim por diante.

C ++ fornece um modelo padrão chamado bitset . Experimente, se quiser.

Você poderia tentar:

 bool i[8] = {0,0,1,1,0,1,0,1}