We know from grade school that a - b = a + (-b). And that is how logic does it we dont subtract we add the negative. We also know from beginner programming classes that with twos complement to get the negative you invert and add one. a - b = a + (~b) + 1. We also know from grade school the concept of carrying. 9+3 = 2 carry the one. Same in binary, with two operands you can have 1 + 1 = 0 carry the one. So each column in logic needs a carry. Each are three bits in two bits out, the two operands in plus carry in and carry out and the result out. Since each of these logic blobs has an input bit, carry in, normal addition that first carry in is a zero, but for subtraction we can make that carry in a 1 and invert the second operand to get a + b = a + (~b) + 1
So subtraction is addition, if you work through a few simple examples, or better try every three bit combination of operands yourself. You will see that there is no such thing as signed nor unsigned addition (or subtraction), the beauty of twos complement encoding.
Knowing all of this, subtraction is addition, with addition we get a carry out on UNSIGNED overflow, the signed overflow bit is when the carry in and the carry out of the msbit dont match, usually represented as the V flag. Now some architectures, since they are already inverting the b operand on the way in and the carry in on the way in, they invert the carry out on the way out. SOME DONT. So you have to look at your particular architecture to understand if the carry out is considered an unsigned addition overflow or if it is a borrow. or not borrow or whatever.
zero minus something is not always going to have a carry out for the addition.
0b000 - 0b111
0001
000
+ 000
=====
001
The carry out of the addition is zero. Your architecture may choose to leave it that way or it may choose to invert it and call it a borrow.
Within an architecture family. All of the x86s or all of the ARMs it is likely they will continue to do it the same way forever. But there is no reason to expect ARM and MIPS and x86 and XYZ to all do it the same way.
Inverting it and defining it as a borrow makes sense from a terminology perspective.
Note that all of the (signed/unsigned) greater than, less than, greater than or equal, less than or equal definitions are based on the carry/borrow choice for that architecture, you cannot translate those flag comparisions across architectures unless they have the same definition.
-O3
on most-Ofast
for gcc version >= 4.6.0). Compilers are quite good at optimizing today and 9/10 times the straight C will be faster. – David C. Rankin