Oppure

Loading
03/10/17 19:49
AldoBaldo
Buonasera programmatori!

Sono attanagliato da dubbi circa l'affidabilità di alcune macro di manipolazione dei bit in valori numeri con dimensione non uniforme (8, 16, 32 e 64 bit) che vorrei usare in uno di quei tanti esperimenti inconcludenti che di quando in quando mi vengono in mente.

Ho messo insieme un programmino di prova nel quale SEMBRA che tutto funzioni ma, siccome in altri casi ho fatto delle MOSTRUOSITA' che funzionavano nel caso particolare ma erano inaffidabili nella generalità, vi chiedo cortesemente un'opinione. In caso ci siano dei difetti, sareste così gentili da aiutarmi a capire cosa ho sbagliato?

Vai col codice!

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

// per intervenire sui singoli bit di un
// valore numerico con un massimo di 64 bit
#define SETBIT(n,nBit) ((n)|(((uint64_t)(1))<<(nBit)))
#define UNSETBIT(n,nBit) ((n)&(~(((uint64_t)(1))<<(nBit))))
#define INVERTBIT(n,nBit) ((n)^(((uint64_t)(1))<<(nBit)))

void stampa_binario( uint64_t n, uint8_t nBitMin );

int main() {
    uint8_t  n8  = 20;
    uint32_t n32 = 1234567;

    // prova valore a 8 bit
    stampa_binario( n8, 8 ); putchar( '\n' );

    n8 = SETBIT( n8, 6 );
    stampa_binario( n8, 8 ); putchar( '\n' );

    n8 = UNSETBIT( n8, 6 );
    stampa_binario( n8, 8 ); putchar( '\n' );

    n8 = INVERTBIT( n8, 6 );
    stampa_binario( n8, 8 ); putchar( '\n' );

    // prova valore a 32 bit
    stampa_binario( n32, 32 ); putchar( '\n' );

    n32 = SETBIT( n32, 6 );
    stampa_binario( n32, 32 ); putchar( '\n' );

    n32 = UNSETBIT( n32, 6 );
    stampa_binario( n32, 32 ); putchar( '\n' );

    n32 = INVERTBIT( n32, 6 );
    stampa_binario( n32, 32 ); putchar( '\n' );

    return 0;
}

void stampa_binario( uint64_t n, uint8_t nBitMin ) {
    char s[68];
    uint8_t i=0;

    do {
        s[i++] = n%2?'1':'0';
        n >>= 1;
    } while( n != 0 );

    while( i < nBitMin )
        s[i++] = '0';
    s[i] = 'Buonasera programmatori!


Sono attanagliato da dubbi circa l'affidabilità di alcune macro di manipolazione dei bit in valori numeri con dimensione non uniforme (8, 16, 32 e 64 bit) che vorrei usare in uno di quei tanti esperimenti inconcludenti che di quando in quando mi vengono in mente.

Ho messo insieme un programmino di prova nel quale SEMBRA che tutto funzioni ma, siccome in altri casi ho fatto delle MOSTRUOSITA' che funzionavano nel caso particolare ma erano inaffidabili nella generalità, vi chiedo cortesemente un'opinione. In caso ci siano dei difetti, sareste così gentili da aiutarmi a capire cosa ho sbagliato?

Vai col codice!

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

// per intervenire sui singoli bit di un
// valore numerico con un massimo di 64 bit
#define SETBIT(n,nBit) ((n)|(((uint64_t)(1))<<(nBit)))
#define UNSETBIT(n,nBit) ((n)&(~(((uint64_t)(1))<<(nBit))))
#define INVERTBIT(n,nBit) ((n)^(((uint64_t)(1))<<(nBit)))

void stampa_binario( uint64_t n, uint8_t nBitMin );

int main() {
    uint8_t  n8  = 20;
    uint32_t n32 = 1234567;

    // prova valore a 8 bit
    stampa_binario( n8, 8 ); putchar( '\n' );

    n8 = SETBIT( n8, 6 );
    stampa_binario( n8, 8 ); putchar( '\n' );

    n8 = UNSETBIT( n8, 6 );
    stampa_binario( n8, 8 ); putchar( '\n' );

    n8 = INVERTBIT( n8, 6 );
    stampa_binario( n8, 8 ); putchar( '\n' );

    // prova valore a 32 bit
    stampa_binario( n32, 32 ); putchar( '\n' );

    n32 = SETBIT( n32, 6 );
    stampa_binario( n32, 32 ); putchar( '\n' );

    n32 = UNSETBIT( n32, 6 );
    stampa_binario( n32, 32 ); putchar( '\n' );

    n32 = INVERTBIT( n32, 6 );
    stampa_binario( n32, 32 ); putchar( '\n' );

    return 0;
}

void stampa_binario( uint64_t n, uint8_t nBitMin ) {
    char s[68];
    uint8_t i=0;

    do {
        s[i++] = n%2?'1':'0';
        n >>= 1;
    } while( n != 0 );

    while( i < nBitMin )
        s[i++] = '0';
    s[i] = '{parsed_message}';

    while( i>0 ) putchar( s[--i] );
}
'; while( i>0 ) putchar( s[--i] ); }
ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
03/10/17 20:41
lumo
Il codice è giusto, ovviamente per valori di n ragionevoli e con i soliti accorgimenti per quando si usano le macro.
aaa
04/10/17 7:11
AldoBaldo
Sì, per "valori ragionevoli" intendiamo la gamma possibile entro un certo numero di bit (tipo 0-255 per gli 8 bit, ecc.), questo lo davo per assodato.

I "soliti accorgimenti"... intendo la cosa in questo modo: tenere presente che "invocare" una macro è come trascrivere il testo della macro stessa nel punto esatto in cui la "invochi" (tenendo presente che i "parametri" vengono inseriti per "sostituzione" nel testo stesso), giusto?E' sufficiente?

Forse è meglio che faccia un esempio più esplicito, che coi giri di parole rischio di non essere chiaro (problemi col lessico tecnico, che conosco solo a spanne).

uint16_t val = 0;

// scrivere cosi'...

val = SETBIT( val, 2 );

// ... e' come scrivere ESATTAMENTE cosi',
// nello stesso punto del codice...

val = ((val)|(((uint64_t)(1))<<(2)));

// dando come risultato 0000000000000100, cioe' 4
ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
05/10/17 13:14
lumo
Sì, direi che non c'è molto da aggiungere, se non che forse si potrebbe anche usare una funzione inline in questo caso, il compilatore non dovrebbe avere problemi a generare un codice ottimizzato allo stesso modo.
aaa
05/10/17 17:09
AldoBaldo
Bene! Grazie per le rassicurazioni, ora posso usare più a cuor leggero quelle "scorciatoie".
Ultima modifica effettuata da AldoBaldo 05/10/17 17:10
ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.