2013-02-27 10 views
13

Come si usa il prefisso 0x per i numeri esadecimali e o per quelli ottali, c'è qualcosa che può essere fatto per i numeri binari?Scrittura del sistema di numeri binari nel codice C

Ho provato il suffisso b, ma il GCC non lo consentiva.

Error: invalid suffix "b" on integer constant

È possibile?

+3

I letterali binari non esistono in C. Il più vicino che hai sono esadecimali, poiché seguono da vicino il bitpattern binario. –

+1

Hex to binary è davvero facile da convertire. –

+0

Octal è anche disponibile, scritto 0666 e così (/ me anatre e corre) – vonbrand

risposta

30

Standard C non definisce costanti binarie. C'è un GNU (credo) l'estensione anche se (tra i compilatori popolari, clang si adatta pure): il prefisso 0b:

int foo = 0b1010; 

Se si vuole attaccare con standard di C, poi c'è un'opzione: è possibile combinare un macro e una funzione per creare un quasi leggibile funzione "costante binario":

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

e poi si può usare in questo modo:

int foo = B(1010); 

Se si attivano ottimizzazioni del compilatore pesanti, molto probabilmente il compilatore eliminerà completamente la chiamata alla funzione (piegatura costante) o lo incoraggerà almeno in linea, quindi questo non sarà nemmeno un problema di prestazioni.

Prova:

Il codice seguente:

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

è stato compilato utilizzando clang -o baz.S baz.c -Wall -O3 -S, ed è generato il seguente montaggio:

.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 

Così clang completamente eliminata la chiamata la funzione e sostituito il suo valore di ritorno con 101. Pulito, eh?

+0

La prossima domanda è, perché hai scritto 'foo = [lungo pasticcio di numeri binari]' piuttosto che 'foo = CONSTANT1 | COSTANTE2 | ...; '. Cosa ha ottenuto il numero binario? – Lundin

+5

@Lundin Huh? Il punto è la leggibilità e la presenza di ** valori letterali binari **. –

+0

E il mio punto è che non esiste alcuna situazione in cui i letterali binari siano più leggibili di qualcos'altro, più adatti, come le maschere di bit definite. – Lundin

5

prefisso letterale con 0b come in

int i = 0b11111111; 

Vedi here.

+8

È un'estensione, e potrebbe aver bisogno di un flag speciale per 'gcc' per capirlo. E naturalmente non portatile per altri compilatori che non supportano tale estensione. –

5

Utilizzare BOOST_BINARY (Sì, è possibile utilizzarlo in C).

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

Questa macro viene espansa su un valore letterale ottale durante la preelaborazione.

Problemi correlati