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).
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;
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 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):
Vantagens :
spending processor time
em operações inúteis ( like "?.. :..", "<<", "+"
) para o programa executável (pode ser executado centenas de vezes na aplicação final); "mainly in C"
compiladores "mainly in C"
e em C ++ (a template+enum solution works only in C++ compilers
); "enum solution" (usually 255 = reach enum definition limit)
, diferentemente, "literal constante" limitações, no o compilador permite números maiores; 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()"
); 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}