Integer overflow int and char

I have two examples:

1
2
3
4
5
6
7
8
9
10
11
12

unsigned long l = ULONG_MAX; 
char c = -1; 
if (c == l)
    std::cout << "-1 = 4,294,967,295?";
output:"-1 = 4,294,967,295?"

unsigned char l = 255; 
char c = -1; 
if (c == l)
    std::cout << "-1 = 4,294,967,295?"; 
output:

Why first example generates output but second not?
You should specify signed char since that's what you are assuming (and char is not always signed). It's also more intesting, since switching from signed char to unsigned char changes the result.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <climits>

int main() {
    {
    unsigned long l = ULONG_MAX; 
    signed char c = -1; 
    if (c == l)
        std::cout << "ONE\n";
    }

    {
    unsigned char l = 255; 
    signed char c = -1; 
    if (c == l)
        std::cout << "TWO\n";
    }
}

In the first example, c is first "promoted" to int (with value -1) and then converted (with sign-extension, interestingly, yielding all 1s) to unsigned long for the comparison operator.

In the second, they are both converted to ints for the comparison operator, so one is 255 and the other is -1.

It's generally not a good idea to compare signed and unsigned values and your compiler should give you a warning, so the result is pretty meaningless.
Yes, it's unintuitive behavior. You should avoid comparing signed and unsigned integers in the first place! I wish GCC would give a warning, but it actually only seems to give a warning on your first example...

Here's the thing. When you compare values that are smaller in size than int, the compiler does integer promotion, making those values both ints, regardless of signed vs unsigned. This is what's happening in your second example; both are being promoted to ints in the comparison. And 255 != -1.

In your first example, since unsigned long is >= int, integer promotion does not happen, but the normal rules of unsigned and signed behavior happens: When comparing signed with unsigned, the compiler converts the signed value to unsigned, so -1 becomes ULONG_MAX.

This seems like a good blog post that explains the behavior you're seeing:
https://blog.regehr.org/archives/268

Also, why hardcode the numbers in the print statement's numbers? Different compilers will have different max numbers, hence the use of things like ULONG_MAX.

Edit:
Also, your title is wrong. No integer overflow is happening. Integer overflow is a specific thing that causes undefined behavior.
Last edited on
Topic archived. No new replies allowed.