Funzione che inverte i bit di una byte

di Anonimizzato12211 il
15 risposte
Volevo chiedere se in C, esiste una funzione apposita che dato un byte, ne inverte i bit al suo interno..una sorta di mirror dei bit..

es: byte: 0001 1011 (valore intero 27).

La funzione deve restituire il byte cosi composto: 1101 1000 (intero 216)

15 Risposte

  • No, non esiste. Te la puoi scrivere abbastanza facilmente ...

    P.S. Non "una" byte ma "un" byte ...
  • Perdona l'ignoranza.. avendo una varaibile di tipo unsigned char.. come faccio a puntare al singolo bit al suo interno?
  • Con questi operatori

  • Gli operatori di shift, di scorrimento, di complemento etc li conosco, ma non riesco ad ottenere quello che serve a me.. per usare quegli operatori significa che c deve essere qualche proprietà logica-aritmetica sui bit.. invece l'inversione da sx verso dx dei bit non rispetta nessuna proprietà nota.. almeno credo..

    ps: per inversione non intendo da 0 a 1, ma che il bit 0 va nella posizione 7, il bit 1 nella pos 6, etc..
  • Non sono stato chiaro ... i due operatori che devi usare sono & e |

    Per testare (o azzerare) il singolo bit devi usare l'operatore

    &

    per impostare a 1 il singolo bit, l'operatore

    |
  • Cosi è piu chiaro.. l'ho fatta poi.. funziona.. grazie del supporto.
  • Io opterei per la piu semplice e veloce funzionalità gia nota dal 386:
    
    #include <stdio.h>
    #include <stdlib.h>
    
    void printb(char val)
    {
       int k;
       for(k=0; k < 8 ;k++)
       {
            printf("%d", (val >> (8 - 1 - k)) & 0x01);
       }
    }
    
    int main()
    {
        char num = 27;
    
        printb(num);
        puts("");
    
        asm(
            "ROL $3,%%al"
            :"=a" (num) :"a" (num)
           );
    
        printb(num);
        puts("");
    
        return 0;
    }
    
  • Ma scusa se vuoi invertire i bit di un byte
    basta che fai una not o semplicemente moltiplichi per -1
    esempio
    00100011 cioe 35 in decimale facendo una semplice not ovvero moltiplicndo per -1 avrai
    11011100 = 220
    senza usare operatori che appesantiscono e rendono meno chiaro il codice!
  • @vbextreme
    L'istruzione ROL ruota i bit a sinistra ma NON fa quello che è stato chiesto.
    Solo nel caso indicato, con una rotazione di 3 bit *casualmente* ottieni il risultato richiesto, ma non in tutti i casi (ricorda che chiede il mirror). La rotazione non risolve.


    @smalldragon
    Anche il NOT non c'entra nulla con l'operazione richiesta ... forse non hai capito bene ... non deve invertire il valore dei bit ma la loro posizione.
  • Scusatemi ho capito male
    comunque non credo che in c si possa fare visto che, da quanto ne so, non c'è modo di utilizzare i flag e per quosto tipo di operazione serve il flag di riporto.
    perchè l'operatore da usare sarebbe lo shift inquanto :
    se noi vogliamo trasformare esempio
    0001 1011 (valore intero 27) in 1101 1000 (intero 216)
    dovremo fare :
    0001 1011 shift sinistro di 1 avremo 00110110 riporto = 0
    00110110 shift sinistro di 1 avremo 0110110 riporto = 0
    0110110 shift sinistro di 1 avremo 110110 riporto = 0
    110110 shift sinistro di 1 avremo 10110 riporto = 1
    10110 shift sinistro di 1 avremo 0110 riporto = 1
    etc etc
    secondo voi negli spazi bianchi vicino al numero che valore ci andrà ?
    gli operatori che aggiscono sui bit, shift e rotazione, per riempire gli spazi vuoti usano per default lo zero. "perdendo" il bit che hanno preso e messo nel flag di riporto (cf).
    secondo me l'unico modo per fare questo tipo di operazione sarebbe quella di utilizzare il buon vecchio assembler.
    la procedura grosso modo e la seguente:
    mov ax,variabile
    mov cx,?? ; dove ?? rappresenta il numero di shift che vuoi fare
    ciclo:
     shl ax,1
     adc ax,0  
     loop ciclo       
    
  • Non devi usare operatori di shift/rotazione ... ma hai letto le risposte e il fatto che ha risolto?

    Devi considerare un caso generale in cui nel byte ci sia un valore

    abcdefgh

    e vuoi ottenere

    hgfedcba

    semplicemente con and e or bit a bit
  • Mi fa piacere per lui che ha risolto io quando ho una soluzione la propongo lo stesso per dare l'opportunità di imparare anche altre vie.
    (in fondo e questo lo scopo di questi forum imparare dalle esperienze altrui o sbaglio?)
    guarda che lo shift + la somma con il riporto fa proprio al caso generale.
    solo che nel mio ultimo post ho commesso un grave errore,e di questo mi scuso, perchè la sequenza giusta e la seguente:
    xor bx,bx
    mov ax,variabile
    mov cx,7
    clc
    ciclo:
    shr ax,1
    adc bx,0
    shl bx,1
    loop ciclo
    mov variabile,bx
    con and e or bit a bit e più difficile perchè ogni volta ti devi costruire una maschera di bit che effettua lo spostamento.
    questo tipo di operazioni "and e or bit a bit" sono più indicate per costruire un byte da zero posizionandoti i bit come meglio credi.
    se invece devi semplicemente invertire l'ordine dei bit di un byte, e da quanto l'utente a scritto è questo e il caso, e piu' facile e piu' intuitiva la soluzione con il doppio shift.
  • Il codice che hai scritto non è corretto (basta controllare con il valore 128)

    Il codice corretto che può fare quanto richiesto con shift/rotazioni *in assembly* è questo
    
    		xor bx,bx
    		mov ax,variabile
    		mov cx,8
    	ciclo:
    		shr ax,1
    		rcl bx,1
    		loop ciclo
    		mov variabile,bx
    
    ma in C (che è il linguaggio di cui stiamo discutendo in questo thread, ricordiamolo) scriverai
    
    	unsigned char variabile = 27;
    	unsigned char risultato = 0;
    	int i;
    
    	for(i=0; i<8; i++)
    	{
    		risultato <<= 1;
    		risultato |= (variabile & 1);
    		variabile >>= 1;
    	}
    
    	printf("%u\n", risultato);
    
  • Scusa oregon ho mangiato dell'oca.....
    
    #include <stdio.h>
    #include <stdlib.h>
    
    void printb(char val)
    {
       int k;
       for(k=0; k < 8 ;k++)
       {
            printf("%d", (val >> (8 - 1 - k)) & 0x01);
       }
    }
    
    int main()
    {
        char num = 27;
    
        printb(num);
        puts("");
    
        num = ((num * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
    
        printb(num);
        puts("");
    
        return 0;
    }
    
    in alternativa
    
        num = (num * 0x0202020202ULL & 0x010884422010ULL) % 1023;
    
    spero di essere perdonato...
Devi accedere o registrarti per scrivere nel forum
15 risposte