2010-11-11 28 views
13

Cosa succede realmente quando un byte trabocca?Cosa succede realmente quando un byte trabocca?

Dire che abbiamo

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

Se ora facciamo Oltre

byte byte3 = byte1 + byte2; 

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

+5

Il risultato dovrebbe essere 93 ... –

+2

Rimosso i tag C e C++ perché A. C e C++ non hanno un tipo di dati "byte" e B. è un comportamento non definito in base allo standard. –

+0

@Billy ci sono equivalenti in C e C++ –

risposta

11

È piuttosto semplice. Fa solo l'aggiunta e si stacca su un numero con più di 8 bit. Il nono bit (essendo uno) solo 'cade' e si sono lasciati con i restanti 8 bit che formano il numero 94.

(sì, è innocuo)

+0

A proposito, una cosa molto simile accade con i byte firmati (o altri tipi numerici firmati), tranne per un byte firmato ci sono solo 7 bit "dati" e un bit per il segno. Questo è il motivo per cui 127 + 1 = -128 per i byte firmati. (il byte del segno diventa 1 che significa negativo) – Sam

+0

Un sacco di grandi risposte qui (tutti sembravano avere un'immagine molto chiara di questo, ma io :) Difficile scegliere la risposta per accettare, ma ho scelto questo era. Breve e buona spiegazione. Grazie a tutti – ImJames

+1

Questo non è corretto come in C#, il codice dato non verrà compilato. –

5

Il flag di carry viene impostato ... ma oltre il risultato non è quello che ti aspetti, non dovrebbero esserci effetti negativi.

2

Il bit principale è caduto.

6

I bit superiori verranno troncati. Non è dannoso per nessun'altra memoria, è solo dannoso in termini di risultati non voluti.

5

In genere (e il comportamento esatto dipende dalla lingua e dalla piattaforma), il risultato verrà preso in forma-256. vale a dire 150 + 199 = 349. 349 mod 256 = 93.

Ciò non dovrebbe influire su nessun altro archivio.

3

Il comportamento dipende dalla lingua.

In C e C++, l'overflow con segno è indefinito e l'overflow non firmato ha il comportamento menzionato (sebbene non sia presente il tipo byte).

In C#, è possibile utilizzare la parola chiave checked per dichiarare esplicitamente che si desidera ricevere un'eccezione in caso di overflow e la parola chiave unchecked per dichiarare esplicitamente che si desidera ignorarla.

5

Dato che hai codificato la domanda C#, C++ e C, risponderò a proposito di C e C++. In overflow C++ su tipi firmati, incluso sbyte (che, credo, sia signed char in C/C++) genera un comportamento non definito. Tuttavia, per i tipi non firmati, come ad esempio (che è unsigned char in C++), il risultato è il modulo 2 n dove n è il numero di bit nel tipo senza segno. 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#.

+0

'byte' è' unsigned char' in WinDef.h. Ovviamente * potrebbe * essere qualsiasi cosa, ma penso che ci venga chiesto di Windows. –

+0

@steve: ho detto altrimenti? –

+0

@Armen: sto chiamando il tuo bluff. Sì, l'hai fatto, ma poi hai modificato. –

2

E si verifica un trabocco 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 es. la memoria non ha overflow in un'altra posizione.

8

In C#, se si dispone di

checked { byte byte3 = byte1 + byte2; } 

Sarà 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;

+0

Questo codice non viene compilato. Quando lo aggiusti, la vera risposta diventa ovvia. –

+1

Quale, l'esempio o l'esempio in linea. Le persone con rep 3k + non hanno la possibilità di correggere le risposte? –

+0

Questo non è corretto in quanto i byte vengono promossi a ints nell'aggiunta, risultando in un int. Pertanto, questo codice non verrà compilato senza un cast. –

4

L'overflow è innocuo in C# - non si ha un sovraccarico di memoria - si ottengono semplicemente gli ultimi 8 bit del risultato. Se si desidera questa eccezione, utilizzare la parola chiave 'checked'. Si noti inoltre che è possibile trovare byte + byte come int, quindi potrebbe essere necessario eseguire il cast back to byte.

1

Diamo un'occhiata a ciò che accade realmente (in C (presupponendo che tu abbia il tipo di dati appropriato, come alcuni hanno sottolineato che C non ha un tipo di dati "byte", tuttavia ci sono tipi di dati a 8 bit che possono Essere aggiunto)). 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 verifica 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'è una certa complessità nell'imballaggio dei byte e nello stack anche 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).

+0

Tutto questo per dire che si è verificato un overflow aritmetico - questo deve essere il motivo per cui ti chiamano Mc * Waffle * stix

+0

@softwaremonkey: hehe, beh, il fatto è che non è proprio un overflow aritmetico; nello spazio operativo in cui viene eseguita l'operazione, non c'è overflow e nessun problema. È utile capire che queste cose si verificano nel modo in cui lo fanno. Inoltre, nota che stavo parlando di C in origine ... –

1

Per quanto riguarda C#, l'aggiunta di due valori di tipo byte produce un valore di tipo int che deve quindi essere restituito a byte.

Pertanto, l'esempio del codice genererà 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); 

See MSDN for more details su questo. Inoltre, vedere lo C# language specification, sezione 7.3.6 Promozioni numeriche.

Problemi correlati