Cosa succede realmente quando un Byte trabocca?

Cosa succede realmente quando un Byte trabocca?

Dì che abbiamo

byte byte1 = 150; // 10010110 byte byte2 = 199; // 11000111 

Se ora facciamo questa aggiunta

 byte byte3 = byte1 + byte2; 

Penso che finiremo con byte3 = 94 ma cosa succede realmente? Ho sovrascritto qualche altra memoria in qualche modo o è totalmente innocuo?

È abbastanza semplice Fa solo l’aggiunta e si stacca su un numero con più di 8 bit. Il nono bit (essendo uno) “cade” e ti rimangono gli 8 bit rimanenti che formano il numero 94.

(sì, è innocuo)

In C # se lo hai

  checked { byte byte3 = byte1 + byte2; } 

Lancia un’eccezione di overflow. Il codice è compilato unchecked per impostazione predefinita. Come dicono le altre risposte, il valore si “avvolge”. cioè, byte3 = (byte1 + byte2) & 0xFF;

I primi bit saranno troncati. Non è dannoso per nessun’altra memoria, è solo dannoso in termini di risultati non voluti.

La bandiera carry viene impostata … ma oltre al risultato che non è quello che ti aspetti, non dovrebbero esserci effetti negativi.

Tipicamente (e il comportamento esatto dipenderà dal linguaggio e dalla piattaforma), il risultato sarà preso modulo-256. cioè 150 + 199 = 349. 349 mod 256 = 93.

Questo non dovrebbe influenzare nessun altro spazio di archiviazione.

Dato che hai taggato la tua domanda C #, C ++ e C, risponderò a proposito di C e C ++. In overflow c ++ su tipi firmati, incluso sbyte (che, credo, è signed char in C / C ++) produce un comportamento indefinito. Tuttavia, per i tipi non firmati, come il byte (che è un unsigned char in C ++), il risultato è il modulo 2 n dove n è il numero di bit nel tipo unsigned. In C # viene mantenuta la seconda regola e i tipi firmati generano un’eccezione se si trovano nel blocco checked . Potrei sbagliarmi nella parte C #.

L’overflow è innocuo in c # – non si riversa troppo nella memoria – si ottengono semplicemente gli ultimi 8 bit del risultato. Se si desidera questa eccezione, utilizzare la parola chiave ‘checked’. Si noti inoltre che è ansible trovare byte + byte come int, quindi potrebbe essere necessario eseguire il cast back to byte.

Il comportamento dipende dalla lingua.

In C e C ++, l’overflow con segno non è definito e l’overflow non firmato ha il comportamento che hai menzionato (anche se non esiste un tipo di byte ).

In C #, puoi usare la parola chiave checked per dire esplicitamente che vuoi ricevere un’eccezione se c’è overflow e la parola chiave unchecked per dire esplicitamente che vuoi ignorarla.

Il pezzo principale è appena caduto.

E si verifica un overflow aritmetico. Da 150 + 199 = 349, binario 1 0101 1101, il 1 bit superiore viene rilasciato e il byte diventa 0101 1101; cioè il numero di bit che un byte può contenere overflow.

Nessun danno è stato fatto – ad esempio la memoria non ha overflow in un’altra posizione.

Diamo un’occhiata a cosa succede realmente (in C (assumendo che tu abbia il tipo di dati appropriato, come alcuni hanno sottolineato che C non ha un tipo di dati “byte”, tuttavia ci sono dei tipi di dati a 8 bit che possono essere aggiunti)) . Se questi byte sono dichiarati nello stack, esistono nella memoria principale; ad un certo punto, i byte verranno copiati sul processore per l’operazione (sto saltando diversi passaggi importanti, come processsor cacheing …). Una volta nel processore, saranno memorizzati nei registri; il processore eseguirà un’operazione di aggiunta su questi due registri per aggiungere i dati insieme. Ecco dove si manifesta la causa della confusione. La CPU eseguirà l’operazione di aggiunta nel tipo di dati nativo (o talvolta specificato). Diciamo che il tipo nativo della CPU è una parola di 32 bit (e che quel tipo di dati è ciò che viene usato per l’operazione di aggiunta); ciò significa che questi byte saranno memorizzati in parole a 32 bit con i 24 bit superiori non impostati; l’operazione add farà effettivamente l’overflow nella parola target a 32 bit. Ma (ed ecco il bit importante) quando i dati vengono copiati dal registro allo stack, solo gli 8 bit più bassi (il byte) verranno ricopiati nella posizione della variabile di destinazione nello stack. (Si noti che c’è anche una certa complessità nell’imballaggio dei byte e nello stack qui.)

Quindi, ecco il risultato; l’add provoca un overflow (a seconda delle specifiche istruzioni del processore selezionate); i dati, tuttavia, vengono copiati dal processore in un tipo di dati della dimensione appropriata, quindi l’overflow è invisibile (e innocuo, presupponendo un compilatore scritto correttamente).

Per quanto riguarda C #, aggiungendo due valori di tipo byte insieme si ottiene un valore di tipo int che deve quindi essere restituito a byte .

Pertanto il tuo esempio di codice risulterà in un errore del compilatore senza un ritorno al byte come nel seguito.

 byte byte1 = 150; // 10010110 byte byte2 = 199; // 11000111 byte byte3 = (byte)(byte1 + byte2); 

Vedi MSDN per maggiori dettagli su questo. Inoltre, consultare le specifiche del linguaggio C # , sezione 7.3.6 Promozioni numeriche.