Come si può dire la differenza tra ASCII in binario e lo stesso decimale in binario?


Risposta 1:

In generale, non puoi, non solo dai bit. Ad esempio, il numero 00111001 in binario: potrebbe anche essere il numero 57, ma potrebbe anche essere la cifra ASCII “9”.

Detto questo, in pratica puoi spesso dire la differenza. Perché avrai qualche idea su quale valore dovrebbe essere con cui stai lavorando. Considera la seguente funzione C, che contiene un bagliore evidente:

int print (int n) {char buf [1]; int i; i = 3 * n + 2; sprintf (buf, "% i \ n", i); puts (BUF); ritorno i; }

Calcola, per ogni numero intero n, il valore 3 * n + 2, scarica questo valore sulla console e restituisce il valore come intero. Tuttavia, durante il test di questa funzione è possibile notare che se l'input è, diciamo 9, stampa il risultato corretto 29 sulla console. Ma restituirà il valore sbagliato, in questo caso il valore 57. E questo potrebbe darti qualche indizio su cosa sta succedendo qui, poiché noterai che 57 è la rappresentazione ASCII del numero 9, e che sembra essere l'ultima cifra del risultato.

Quindi fai qualche sperimentazione e scopri che questo è vero ogni volta che il risultato è un numero di 2 cifre. Ad esempio, con n = 5 il risultato dovrebbe essere 17, ma invece il risultato è 55, la rappresentazione ASCII della cifra “7”.

E quando il risultato ha più di 2 cifre, il risultato è ancora più strano. Ad esempio, con n = 50, il risultato corretto 152 viene scaricato sulla console, ma il valore restituito è 12853 in decimale o 0x3235 in esadecimale. Potresti notare che questa è la rappresentazione ASCII della stringa "25", o le ultime due cifre del risultato, in ordine inverso!

Quindi, cosa sta succedendo qui? Si noti che il buffer dei caratteri ha spazio solo per un singolo carattere! La funzione sprintf () in C non controlla i sovraccarichi del buffer, quindi scriverà felicemente il suo output nella memoria puntata da buf, sovrascrivendo i byte immediatamente successivi ai byte riservati per buf se buf è troppo piccolo. In questo caso, questi sono i byte riservati per l'intero i e vengono sovrascritti. E poiché il valore di i viene quindi utilizzato come valore di ritorno di questa funzione, il valore di ritorno sarà errato.

Rimane solo una domanda: perché il valore restituito contiene le ultime cifre ASCII del risultato, ma in ordine inverso? Ciò accade perché (supponendo che tu stia lavorando su un PC) i byte di un numero intero vengono memorizzati "nel modo sbagliato". Ad esempio, il numero intero a 32 bit 0x12345678 viene memorizzato come byte 0x78 0x56 0x34 0x12 in memoria.

Pertanto, quando l'ingresso è n = 50, la prima cifra del risultato verrà memorizzata in buf, mentre la seconda e la terza cifra del risultato finiranno in i, che diventerà, in byte, 0x35 0x32 0x00 0x00. E questo rappresenta il valore 0x3235 = 12853 in decimale quando interpretato come un numero a 32 bit.

Come nota finale: se dovessi davvero provare questo sulla tua macchina, i risultati potrebbero essere diversi, poiché gli effetti di questo tipo di errore dipendono fortemente dal funzionamento interno della tua macchina e del tuo compilatore. Ad esempio, uno smartphone memorizzerà spesso i suoi byte nell'ordine corretto, quindi di conseguenza otterrai un numero diverso. E il tuo compilatore potrebbe riservare più di 1 byte per buf a causa di problemi di allineamento della memoria, oppure potrebbe salvare buf e i viceversa (prima in memoria, poi in buf). Oppure può ottimizzare i via mantenendo solo il risultato in un registro CPU. Nel qual caso il risultato sarà corretto ma qualcos'altro in memoria verrà danneggiato.

In generale, se i programmi contengono bug come questo, tutte le scommesse riguardano cosa accadrà effettivamente.


Risposta 2:

Se 48 è la rappresentazione ASCII del numero zero e 57 è la rappresentazione ASCII di nove, quindi il nibble meno significativo è la cifra effettiva rappresentata:

0000 0000-0011 0000 = 32 + 16 + 0 = 48

0000 0001-0011 0001

0000 0010-0011 0010

0000 0011-0011 0011

0000 0100-0011 0100

0000 0101-0011 0101

0000 0110-0011 0110

0000 0111-0011 0111

0000 1000-0011 1000

0000 1001-0011 1001 = 32 + 16 + 8 + 1 = 57

o semplicemente; sottrai 48 per darti il ​​numero.