C leggere i byte che rappresentano un int

di il
15 risposte

C leggere i byte che rappresentano un int

So che in base all'Endianness i Byte in memoria sono disposti in modo diverso, per verifica volevo controllare la disposizione dei byte che rappresentano un intero sensa segno da 4Byte:
Nei testi consultati non ho trovato come leggere la memoria partendo da un indirizzo byte a byte.
il seguente codice:

    int i;
    unsigned int ui = 4059231220;

    printf( "valore HEX: 0x%X\nvalore DEC: %u\nBytes occupati: %d\nLocazione relativa di partenza: %X \n\n" ,ui,ui, sizeof(ui), &ui);

    for (i=0; i<sizeof(ui);i++){
        printf("%X \n" , ui);
    }
giustamente stampa tutti e 4 i byte che compongono ui per 4 volte.
Come si legge e stampa un sigolo byte contenuto in un indirizzo, che poi posso incrementare con i, per stampare i successivi byte?
grazie anticipate.

15 Risposte

  • Re: C leggere i byte che rappresentano un int

    Magari esistono delle istruzioni specifiche in C/C++ ma penso che potresti comunque utilizzare la tecnica della mascheratura dei bit/byte ...
    qualcosa del genere, sintassi a parte :
    
    ? myvar & #000000FF
    ? myvar & #0000FF00
    
    e così via
  • Re: C leggere i byte che rappresentano un int

    
    #include <stdio.h>
    #include <inttypes.h>
    
    int main(){
        uint32_t ui = 0x01020304;
        uint8_t * ptr = (uint8_t *)&ui;
        printf("%02x ", *ptr++);
        printf("%02x ", *ptr++);
        printf("%02x ", *ptr++);
        printf("%02x ", *ptr);
     return 0;
     }
    
    Edit: uint8_t al posto di char
  • Re: C leggere i byte che rappresentano un int

    Weierstrass ha scritto:


    
    #include <stdio.h>
    #include <inttypes.h>
    
    int main(){
        uint32_t ui = 0x01020304;
        uint8_t * ptr = (uint8_t *)&ui;
        printf("%02x ", *ptr++);
        printf("%02x ", *ptr++);
        printf("%02x ", *ptr++);
        printf("%02x ", *ptr);
     return 0;
     }
    
    Edit: uint8_t al posto di char
    La parte della conversione di tipo per fare in modo che il puntatore punti un dato a 8 bit invece che a 32, l'ho capita.
    Invece non capisco perché la prima locazione la stampi per ultimo, questo implica la conoscenza a priori della disposizione interna dei valori?

    Comunque l'esempio è già un grande insegnamento.

    per l'EDIT
    Certo, un char è a 8 bit, ma poi genera delle anomalie nella stampa.

    EDIT:
    Capito il ++ è dopo ptr, l'ultimo è già incrementato.
    Tutto chiaro rigrazie.
  • Re: C leggere i byte che rappresentano un int

    Se il primo byte stampato è 04 allora l'architettura è Little Endian, come è molto probabile che sia (è l'architettura più semplice per fare i calcoli). Se il primo è 01 allora è Big Endian
  • Re: C leggere i byte che rappresentano un int

    Quanto imparato oggi da Weierstrass ha prodotto il seguente codice:
    
    #include <stdio.h>
    #include <inttypes.h>
    
    int main()
    {
        int i;
        uint32_t ui = 0x01020304;
        uint8_t * ptrui = (uint8_t *)&ui;
        printf( "valore HEX: %08X\nvalore DEC: %u\nByte occupati: %d\nLocazione relativa di partenza: 0x%X \n\n" ,ui,ui, sizeof(ui), &ui);
        printf("Disposizione in memoria dei byte che rappresentano: 0x%08X\n", ui);
    
        for (i=0; i<sizeof(ui); i++){
             printf("%02X ", *(ptrui+i));
        }
        // 04 all'inizio Little Endian, 04 alla fine Big Endian
        if (*ptrui == 0x04){
            printf ("little endian ");
        }
        else{
            printf ("big endian ");
        }
    
        char ca[10] = {'m','M','Z','F','Y','H'}; // il compilatore azzera gli indici non inseriti
        printf("\n\nStringa = %s\ncaratteri HEX: ", ca);
        uint8_t * ptrca = (uint8_t *)&ca;
        for (i=0; i<sizeof(ca); i++){
            printf( "%02X ", ca[i]);
        }
        printf("\nByte occupati %d\nLocazione relativa di partenza: 0x%X \n" ,sizeof(ca), &ca);
        printf("\nDisposizione in memoria dei byte che rappresentano: %s\n", ca);
        for (i=0; i<sizeof(ca); i++){
             printf("%02X ", *(ptrca+i));
        }
        printf("\n");
        return 0;
    }
    
  • Re: C leggere i byte che rappresentano un int

    Invece non capisco perché la prima locazione la stampi per ultimo, questo implica la conoscenza a priori della disposizione interna dei valori?
    Non dico di leggere un libro di base di informatica ma almeno wikipedia ...

    https://it.wikipedia.org/wiki/Ordine_dei_byt

    Nel codice del tuo primo post i byte li avresti potuto ottenere con
    
        for (i=0; i<8*sizeof(ui); i+=8)
            printf("%X \n" , (unsigned char)((ui>>i) & 0xFF));
    
    senza doverli leggere in memoria ma partendo dal valore.

    Comunque l'esempio è già un grande insegnamento.
    L'esempio viene sempre dopo per "confermare" gli insegnamenti ricevuti. E questi si ricevono dai libri, dai corsi, dallo studio (in generale) della "teoria" prima che della pratica.
  • Re: C leggere i byte che rappresentano un int

    @oregon

    Rubik ha scritto:


    Invece non capisco perché la prima locazione la stampi per ultimo, questo implica la conoscenza a priori della disposizione interna dei valori?
    EDIT:
    Capito il ++ è dopo ptr, l'ultimo è già incrementato.
    Tutto chiaro rigrazie.
    se posti tutto il messaggio, vedi che ci sono arrivato da solo.

    oregon ha scritto:


    Non dico di leggere un libro di base di informatica ma almeno wikipedia ...

    https://it.wikipedia.org/wiki/Ordine_dei_byt
    grazie per il link, ma sono argomenti che conosco e ho studiato 30 anni fa e mi sono tuttora chiari.

    oregon ha scritto:


    Nel codice del tuo primo post i byte li avresti potuto ottenere con
    
        for (i=0; i<8*sizeof(ui); i+=8)
            printf("%X \n" , (unsigned char)((ui>>i) & 0xFF));
    
    senza doverli leggere in memoria ma partendo dal valore.
    grazie per l'esempio, non conoscevo questa possibilità, come ho sempre affermato, sono all'inizio con il C, e la sintassi del C per ottenere un dato risultato non è delle più "logiche", almeno finquando non gli hai preso le misure.

    oregon ha scritto:


    L'esempio viene sempre dopo per "confermare" gli insegnamenti ricevuti. E questi si ricevono dai libri, dai corsi, dallo studio (in generale) della "teoria" prima che della pratica.
    Esatto, infatti dopo aver studiato i puntatori, le tipologie di dato, come stampare attraverso la consolle i dati, come ottenere un indirizzo di memora e un dato entrocontenuto, come convertire i dati da una tipologia all'altra... Non avevo realizzato che per stampare/leggere un byte dovevo convertire il puntatore a unsigned char o uint8_t, cosa diventata palesemente chiara con l'esempio.
    Se non avessi studiato, l'esempio l'avrei saputo solo copiare e non capire.
  • Re: C leggere i byte che rappresentano un int

    Rubik ha scritto:



    grazie per il link, ma sono argomenti che conosco e ho studiato 30 anni fa e mi sono tuttora chiari.
    Beh, dal primo post non sembrava, avrò equivocato.
    grazie per l'esempio, non conoscevo questa possibilità
    In effetti, il mio consiglio è di leggerlo un libro di C, dall'inizio. Sono concetti di base che devono essere studiati almeno una volta.
    la sintassi del C per ottenere un dato risultato non è delle più "logiche", almeno finquando non gli hai preso le misure.
    Mah, direi che non è vicina all'essere umano, ma non manca di logica, anzi, la ritengo molto chiara e flessibile. Forse perché provengo dalla gestione in assembly delle CPU ...
  • Re: C leggere i byte che rappresentano un int

    oregon ha scritto:



    Nel codice del tuo primo post i byte li avresti potuto ottenere con
    
        for (i=0; i<8*sizeof(ui); i+=8)
            printf("%X \n" , (unsigned char)((ui>>i) & 0xFF));
    
    senza doverli leggere in memoria ma partendo dal valore.
    Ok per lo shift a destra di 8 bit alla volta ma ho una perplessità, perché fare l'and bit a bit del byte letto con un valore binario 11111111, che di fatto non cambia il risultato? cosa mi sfugge?
  • Re: C leggere i byte che rappresentano un int

    E' inutile, hai ragione. Secondo me è un rimasuglio del (pessimo) esempio di Wikipedia, dove era necessario. Col downcast in effetti non te ne frega niente se entrano bit 1 a sinistra
  • Re: C leggere i byte che rappresentano un int

    No ... non è un rimasuglio di nulla ...

    E' vero, se si fa il downcast l'and finale non è necessario (ma non altera il valore finale).

    Al contrario, se il downcast non si fa o il compilatore non lo permette (vecchi compilatori) o usiamo assembly, l'and lo sostituisce egregiamente.
    
    for (i=0; i<8*sizeof(ui); i+=8)
            printf("%X \n" , ((ui>>i) & 0xFF));
    
  • Re: C leggere i byte che rappresentano un int

    oregon ha scritto:


    Al contrario, se il downcast non si fa o il compilatore non lo permette (vecchi compilatori) o usiamo assembly, l'and lo sostituisce egregiamente.
    Non uso C/C++ e non ne conosco la sintassi,
    mi fa piacere che la mascheratura dei bit (anche da me proposta come idea) sia una possibilità validamente usabile.
    Aver a che fare con i PLC (e da ragazzino con l'assembly) qualcosa pur insegna
  • Re: C leggere i byte che rappresentano un int

    oregon ha scritto:


    No ... non è un rimasuglio di nulla ...

    E' vero, se si fa il downcast l'and finale non è necessario (ma non altera il valore finale).

    Al contrario, se il downcast non si fa o il compilatore non lo permette (vecchi compilatori) o usiamo assembly, l'and lo sostituisce egregiamente.
    
    for (i=0; i<8*sizeof(ui); i+=8)
            printf("%X \n" , ((ui>>i) & 0xFF));
    
    Nebbia dissipata, questo codice è perfettamente comprensibile. Era l'accoppiata downcast e And logico che mi aveva suscitato perplessità, anche se non influiva sul risultato.

    max.riservo ha scritto:


    Non uso C/C++ e non ne conosco la sintassi,
    mi fa piacere che la mascheratura dei bit (anche da me proposta come idea) sia una possibilità validamente usabile.
    Aver a che fare con i PLC (e da ragazzino con l'assembly) qualcosa pur insegna
    Hai ragione, con l'and logico si ottiene una mascheratura, oregon ha azzerato tutti i bit esclusi gli ultimi 8, volendo posso sapere il valore di ogni singolo bit, basta mettere tutti zeri e un uno nella posizione del bit cercato....

    Simile a quello che avevi proposto all'inizio per gruppi di byte:

    max.riservo ha scritto:


    Magari esistono delle istruzioni specifiche in C/C++ ma penso che potresti comunque utilizzare la tecnica della mascheratura dei bit/byte ...
    qualcosa del genere, sintassi a parte :
    
    ? myvar & #000000FF
    ? myvar & #0000FF00
    
    e così via
  • Re: C leggere i byte che rappresentano un int

    Comunque se vuoi leggere la memoria byte a byte o bit a bit, un metodo tipico è questo
    
    #include <stdio.h>
    #include <inttypes.h>
    
    typedef struct {
        unsigned char b0 : 1;
        unsigned char b1 : 1;
        unsigned char b2 : 1;
        unsigned char b3 : 1;
        unsigned char b4 : 1;
        unsigned char b5 : 1;
        unsigned char b6 : 1;
        unsigned char b7 : 1;
    } byte;
    
    void print_hex_object(void * obj, size_t size){
        unsigned char * ptr = (unsigned char *)obj;
        for (size_t i=0; i<size; i++)
            printf("%02hhX " , *ptr++);
        printf("\n");
    }
    
    void print_bin_object(void * obj, size_t size){
        byte * ptr = (byte *)obj;
        for (size_t i=0; i<size; i++, ptr++){
            printf("%hhX" , ptr->b7);
            printf("%hhX" , ptr->b6);
            printf("%hhX" , ptr->b5);
            printf("%hhX" , ptr->b4);
            printf("%hhX" , ptr->b3);
            printf("%hhX" , ptr->b2);
            printf("%hhX" , ptr->b1);      
            printf("%hhX ", ptr->b0);        
        }
        printf("\n");
    }
    
    int main(){
        uint32_t x = 0x01020304;
        uint64_t y = 0x8182838485868788;
        struct {
            uint32_t a;
            uint64_t b;
        } z = {x, y};
        char ca[] = "Hello World!";
        
        print_hex_object(&x, sizeof(x));
        print_hex_object(&y, sizeof(y));
        print_hex_object(&z, sizeof(z));
        print_hex_object(&ca, sizeof(ca));
        
        print_bin_object(&x, sizeof(x));
        print_bin_object(&y, sizeof(y));
        print_bin_object(&z, sizeof(z));
        print_bin_object(&ca, sizeof(ca));   
        
        return 0;
    }
    
Devi accedere o registrarti per scrivere nel forum
15 risposte