19

What actually happens when a Byte overflows?

Say we have

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

If we now do this addition

byte byte3 = byte1 + byte2;

I think we'll end up with byte3 = 94 but what actually happens? Did I overwrite some other memory somehow or is this totally harmless?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ImJames
  • 881
  • 2
  • 9
  • 14
  • 3
    Removed the C and C++ tags because A. C and C++ have no "byte" datatype, and B. it's undefined behavior according to the standard. – Billy ONeal Nov 11 '10 at 17:00
  • @Billy there are equivalents in C and C++ – Armen Tsirunyan Nov 11 '10 at 17:01
  • Sorry, I'll remove them right away. – ImJames Nov 11 '10 at 17:01
  • 1
    This code won't compile. When you fix it, it will also become clear what happens at runtime. This is assuming your [c#] tag was accurate. – Hans Passant Nov 11 '10 at 17:01
  • I wasn't aware there was a difference in how this was handled in C, C++ and C#. Didn't mean to get anyone upset, just wanted to now what happend – ImJames Nov 11 '10 at 17:03
  • 1
    @Armen: Yes, but in C and C++ the result is not "93", it is "Undefined behavior". Therefore the basic tenant of the question is violated. @ImJames: You didn't upset anyone. I just didn't want **you** to be upset when someone came along and took off the tags ;) – Billy ONeal Nov 11 '10 at 17:06
  • @Billy: Read the standard again :) for unsigned types (and note that byte in C# is unsigned and equivalent to C++'s unsigned char) the result is taken modulo 2n. It is UB only for signed types – Armen Tsirunyan Nov 11 '10 at 17:08
  • If `byte` is a typedef of `unsigned char`, there is nothing undefined (\*) about that `C` code (don't know about `C++`, `C#`, `Java`, `Python`, `Cobol`, `...`) **(\*)** The number of bits in an `unsigned char` is implementation defined ... not undefined – pmg Nov 11 '10 at 17:08
  • @Armen: Good point. Doh! I still don't think C and C++ tags are appropriate though. – Billy ONeal Nov 11 '10 at 17:09
  • @Billy: If the OP wants to know the answer for all three languages, just let him :) – Armen Tsirunyan Nov 11 '10 at 17:10
  • @Billy: I think it would be possible to ask this question something like, "on Windows, what happens when `byte` in C# (or the Microsoft-designated equivalent type in other languages) overflows?". Then it could be tagged with C, C++, F#, whatever the questioner likes. As it stands, though, you're right that it's just begging for people to say "byte? In C? Never heard of it mate!" etc. – Steve Jessop Nov 11 '10 at 17:15
  • 1
    @Steve: I don't know about other fields, but anyone who ever worked in comms programming in C typedef'd a byte as an unsigned 8 bit value quicker than you can say "compile". – Lawrence Dol Nov 11 '10 at 18:38
  • This code results in a compiler error in C# as adding two bytes results in an int. To get the value in byte3 requires a cast. – Jeff Yates Oct 12 '11 at 20:01
  • I'm coming from Arduino C++ (at this moment) so have to add: no, compiler will not complain and there will be nothing like "exception" or any other "managed" reaction during run-time. Both mentioned above in comments are not actually features of the language it self, but compiler, platform, framework... etc. – hardyVeles Sep 06 '19 at 22:54

12 Answers12

15

It's quite simple. It just does the addition and comes off at a number with more than 8 bits. The ninth bit (being one) just 'falls off' and you are left with the remaining 8 bits which form the number 94.

(yes it's harmless)

Sam
  • 565
  • 3
  • 8
  • By the way, a very similar thing happens with signed bytes (or other signed numeric types), except for a signed byte there are only 7 'data' bits and one bit for the sign. This is why 127 + 1 = -128 for signed bytes. (the sign byte becomes 1 which means negative) – Sam Nov 11 '10 at 17:03
  • Alot of great answers here (everybody seemed to have a very clear picture of this but me:) Hard to pick the answer to accept but I pick this one was. Short and good explanation. Thanks all – ImJames Nov 11 '10 at 20:48
  • 2
    This is not correct as in C#, the given code won't actually compile. – Jeff Yates Oct 12 '11 at 20:04
  • 1
    @JeffYates - tell him why it won't compile and offer some ways to fix what he is doing. To get it to compile as is: byte byte3 = (byte)(byte1 + byte2) or use byte byte3 = (byte)byte1 + (byte)byte2 these instructions will compile and could possibly overflow byte3 but sometimes for a single byte checksum value you don't care. – Neal Davis Jul 01 '19 at 18:01
8

The top bits will be truncated. It is not harmful to any other memory, it is only harmful in terms of unintended results.

Gavin H
  • 10,274
  • 3
  • 35
  • 42
6

In C# if you have

 checked { byte byte3 = byte1 + byte2; }

It will throw an overflow exception. Code is compiled unchecked by default. As the other answers are saying, the value will 'wrap around'. ie, byte3 = (byte1 + byte2) & 0xFF;

Ian Quigley
  • 500
  • 1
  • 6
  • 22
5

The carry flag gets set... but besides the result not being what you expect, there should be no ill effects.

Hogan
  • 69,564
  • 10
  • 76
  • 117
5

Typically (and the exact behaviour will depend on the language and platform), the result will be taken modulo-256. i.e. 150+199 = 349. 349 mod 256 = 93.

This shouldn't affect any other storage.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
5

Since you have tagged your question C#, C++ and C, I'll answer about C and C++. In c++ overflow on signed types, including sbyte (which, I believe, is signed char in C/C++) results in undefined behavior. However for unsigned types, such as byte (which is unsigned char in C++) the result is takes modulo 2n where n is the number of bits in the unsigned type. In C# the second rule holds, and the signed types generate an exception if they are in checked block. I may be wrong in the C# part.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • `byte` is `unsigned char` in WinDef.h. Obviously it *could* be anything, but I think we're being asked about Windows. – Steve Jessop Nov 11 '10 at 17:02
  • @steve: have I stated otherwise? – Armen Tsirunyan Nov 11 '10 at 17:03
  • @Armen: I'm calling your bluff. Yes you did, but then you edited. – Steve Jessop Nov 11 '10 at 17:05
  • @Steve: I had edited my answer right after I posted it. And then after your comment, which was way later than my edit, I edited again to make the word byte formatted like `byte`. So I guess we just had a synchronization problem – Armen Tsirunyan Nov 11 '10 at 17:07
  • @Armen: yes, that happens. If I get a pageful of results and take a minute to read them, then by the time I come to comment the answers I see could be out of date. Commenting doesn't reload the page, just does an AJAX thing, so what I see can remain out of date for quite a long time... – Steve Jessop Nov 11 '10 at 17:09
  • And of course I was wrong anyway, since it's `BYTE` in WinDef.h, not `byte`. D'oh. – Steve Jessop Nov 11 '10 at 17:12
5

Overflow is harmless in c# - you won't overflow memory - you simply obly get the last 8 bits of the result. If you want this to this an exception, use the 'checked' keyword. Note also that you may find byte+byte gives int, so you may need to cast back to byte.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
3

The behavior depends on the language.

In C and C++, signed overflow is undefined and unsigned overflow has the behavior you mentioned (although there is no byte type).

In C#, you can use the checked keyword to explicitly say you want to receive an exception if there is overflow and the unchecked keyword to explicitly say you want to ignore it.

Alan Geleynse
  • 24,821
  • 5
  • 46
  • 55
2

Leading bit just dropped off.

Andrew Bezzub
  • 15,744
  • 7
  • 51
  • 73
2

And arithmetic overflow occurs. Since 150+199=349, binary 1 0101 1101, the upper 1 bit is dropped and the byte becomes 0101 1101; i.e. the number of bits a byte can hold overflowed.

No damage was done - e.g. the memory didn't overflow to another location.

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
1

Let's look at what actually happens (in C (assuming you've got the appropriate datatype, as some have pointed out that C doesn't have a "byte" datatype; nonetheless, there are 8-bit datatypes which can be added)). If these bytes are declared on the stack, they exist in main memory; at some point, the bytes will get copied to the processor for operation (I'm skipping over several important steps, such as processsor cacheing...). Once in the processor, they will be stored in registers; the processor will execute an add operation upon those two registers to add the data together. Here's where the cause of confusion occurs. The CPU will perform the add operation in the native (or sometimes, specified) datatype. Let's say the native type of the CPU is a 32-bit word (and that that datatype is what is used for the add operation); that means these bytes will be stored in 32-bit words with the upper 24 bits unset; the add operation will indeed do the overflow in the target 32-bit word. But (and here's the important bit) when the data is copied back from the register to the stack, only the lowest 8 bits (the byte) will be copied back to the target variable's location on the stack. (Note that there's some complexity involved with byte packing and the stack here as well.)

So, here's the upshot; the add causes an overflow (depending on the specific processor instruction chosen); the data, however, is copied out of the processor into a datatype of the appropriate size, so the overflow is unseen (and harmless, assuming a properly written compiler).

Paul Sonier
  • 38,903
  • 3
  • 77
  • 117
  • All this to say that an arithmetic overflow occurred - this must be why they call you Mc*Waffle*stix – Lawrence Dol Nov 11 '10 at 18:33
  • @softwaremonkey: hehe, well, the thing is, it's not really an arithmetic overflow; in the operation space in which the operation gets executed, there's no overflow and no problem. It's useful to understand that these things occur in the way they do. Also, note that I was talking about C originally... – Paul Sonier Nov 11 '10 at 18:48
1

As far as C# goes, adding two values of type byte together results in a value of type int which must then be cast back to byte.

Therefore your code sample will result in a compiler error without a cast back to byte as in the following.

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

byte byte3 = (byte)(byte1 + byte2);

See MSDN for more details on this. Also, see the C# language specification, section 7.3.6 Numeric promotions.

Jeff Yates
  • 61,417
  • 20
  • 137
  • 189