Thread: C integer overflow behaviour when assigning to larger-width integers

  1. #1
    Registered User
    Join Date
    Apr 2009
    Posts
    3

    C integer overflow behaviour when assigning to larger-width integers

    If I execute the following code in C:

    Code:
    #include <stdint.h>
    
    uint16_t a = 4000;
    uint16_t b = 8000;
    
    int32_t c = a - b;
    
    printf("%d", c);
    It correctly prints '-4000' as the result. However, I'm a little confused: shouldn't there be an arithmetic overflow when subtracting the larger unsigned integer from the other? What casting rules are at play here? This question seems a bit noobish, so any references would be greatly appreciated.

  2. #2
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    Underflow DID happen, but data is what you define it to be. The result, if interpreted as an unsigned type, would be a big number. If interpreted as a signed type, it would be -4000. A beautiful feature of two's complement system is that adding and subtracting are the same for signed/unsigned in terms of bits in and bits out. The only difference would be in zero-extension vs sign-extension.

    You are storing it into a 32-bit signed type, so it is sign-extended to 32-bits, and that of course will give you -4000.

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You do get an overflow (or rather, underflow, as the second number is greater than the first), but the representation of signed and unsigned is [1] handled by the same instruction, and the only time there is a difference is when converting the number to a string (e.g. printing it) and when dealing with comparative (<, >, >=, <=) operators. All other times, the number is just a set of bits that is operated on with the exact same rules, whether it is signed or unsigned.


    [1]in nearly all processors, but I'm sure if I say it categorically IS so, someone will dig out the 1973 manual of XYZ Corp. and tell me that their 17-bit 93188 processor DOES NOT behave this (product entirely made up).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    Registered User
    Join Date
    Apr 2009
    Posts
    3
    Quote Originally Posted by cyberfish View Post
    Underflow DID happen, but data is what you define it to be. The result, if interpreted as an unsigned type, would be a big number. If interpreted as a signed type, it would be -4000. A beautiful feature of two's complement system is that adding and subtracting are the same for signed/unsigned in terms of bits in and bits out. The only difference would be in zero-extension vs sign-extension.

    You are storing it into a 32-bit signed type, so it is sign-extended to 32-bits, and that of course will give you -4000.
    Ah, I see. So if I want to be able to perform this operation without the possibility of an underflow, I would have to typecast both integers to the larger result type first? e.g.:

    Code:
    uint16_t a = 4000;
    uint16_t b = 8000;
    
    int32_t c = (int32_t)a - (int32_t)b;

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Davorian View Post
    Ah, I see. So if I want to be able to perform this operation without the possibility of an underflow, I would have to typecast both integers to the larger result type first? e.g.:

    Code:
    uint16_t a = 4000;
    uint16_t b = 8000;
    
    int32_t c = (int32_t)a - (int32_t)b;
    That is still underflow, technically speaking, as you are subtracting a larger number from a smaller one - underflow is how you get negative numbers from positive ones!

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User
    Join Date
    Apr 2009
    Posts
    3
    Quote Originally Posted by matsp View Post
    That is still underflow, technically speaking, as you are subtracting a larger number from a smaller one - underflow is how you get negative numbers from positive ones!

    --
    Mats
    Alright

    I understand that on a 2's complement machine, the operation still technically produces an underflow, but I can assume that this pattern will produce the correct result in all cases (on an i386/686 architecture)?

    Note: I'm fairly sure this isn't necessary on 32-bit machines at all because of C's integer promotion rules (ints are 32 bits wide, and therefore most operands are promoted to 32 bits anyway according to the C standard), but if we scale up to a 32/32/64 bit example, the behaviour is not quite so clear-cut. I'm asking about the general case.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Assigning digits to cells in an integer array
    By fred2028 in forum C Programming
    Replies: 1
    Last Post: 10-11-2006, 09:08 AM
  2. load gif into program
    By willc0de4food in forum Windows Programming
    Replies: 14
    Last Post: 01-11-2006, 10:43 AM
  3. Very larger integer calulator
    By Dewayne in forum C++ Programming
    Replies: 2
    Last Post: 09-14-2004, 07:25 PM
  4. how to handle integer overflow in C
    By kate1234 in forum C Programming
    Replies: 8
    Last Post: 04-23-2003, 12:20 PM
  5. Linked Lists Integer addition ? HELP Please??
    By green_eel in forum C Programming
    Replies: 3
    Last Post: 03-12-2003, 04:36 PM

Tags for this Thread