Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

comparison between signed and unsigned integer expressions and 0x80000000

Tags:

c++

I have the following code:

#include <iostream>

using namespace std;

int main()
{
    int a = 0x80000000;
    if(a == 0x80000000)
        a = 42;
    cout << "Hello World! :: " << a << endl;
    return 0;
}

The output is

Hello World! :: 42

so the comparison works. But the compiler tells me

g++ -c -pipe -g -Wall -W -fPIE  -I../untitled -I. -I../bin/Qt/5.4/gcc_64/mkspecs/linux-g++ -o main.o ../untitled/main.cpp
../untitled/main.cpp: In function 'int main()':
../untitled/main.cpp:8:13: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     if(a == 0x80000000)
             ^

So the question is: Why is 0x80000000 an unsigned int? Can I make it signed somehow to get rid of the warning?

As far as I understand, 0x80000000 would be INT_MIN as it's out of range for positive a integer. but why is the compiler assuming, that I want a positive number?

I'm compiling with gcc version 4.8.1 20130909 on linux.

like image 776
Adam Avatar asked Jun 27 '15 12:06

Adam


People also ask

What is the difference between a signed and an unsigned integer?

A signed integer is a 32-bit datum that encodes an integer in the range [-2147483648 to 2147483647]. An unsigned integer is a 32-bit datum that encodes a nonnegative integer in the range [0 to 4294967295]. The signed integer is represented in twos complement notation.

Can we compare signed and unsigned int in C?

The hardware is designed to compare signed to signed and unsigned to unsigned. If you want the arithmetic result, convert the unsigned value to a larger signed type first. Otherwise the compiler wil assume that the comparison is really between unsigned values. And -1 is represented as 1111..

How do you compare unsigned integers?

Java Integer compareUnsigned() method lang package compares two integer values (x, y) given as a parameter, treating the values as unsigned and returns the value zero if (x==y), if (x < y) then it returns a value less than zero and if (x > y) then it returns a value greater than zero.

What is the difference between unsigned int and uint32_t?

unsigned int is an unsigned integer of a system defined size but probably 32 bits. uint32_t is an unsigned integer of 32 bits. Probably the same as unsigned int but not guaranteed to be so. size_t is the type used to specify the size of memory allocations and the underlying type for indexes in the standard library.


1 Answers

0x80000000 is an unsigned int because the value is too big to fit in an int and you did not add any L to specify it was a long.

The warning is issued because unsigned in C/C++ has a quite weird semantic and therefore it's very easy to make mistakes in code by mixing up signed and unsigned integers. This mixing is often a source of bugs especially because the standard library, by historical accident, chose to use an unsigned value for the size of containers (size_t).

An example I often use to show how subtle is the problem consider

// Draw connecting lines between the dots
for (int i=0; i<pts.size()-1; i++) {
    draw_line(pts[i], pts[i+1]);
}

This code seems fine but has a bug. In case the pts vector is empty pts.size() is 0 but, and here comes the surprising part, pts.size()-1 is a huge nonsense number (today often 4294967295, but depends on the platform) and the loop will use invalid indexes (with undefined behavior).

Here changing the variable to size_t i will remove the warning but is not going to help as the very same bug remains...

The core of the problem is that with unsigned values a < b-1 and a+1 < b are not the same thing even for very commonly used values like zero; this is why using unsigned types for non-negative values like container size is a bad idea and a source of bugs.

Also note that your code is not correct portable C++ on platforms where that value doesn't fit in an integer as the behavior around overflow is defined for unsigned types but not for regular integers. C++ code that relies on what happens when an integer gets past the limits has undefined behavior.

Even if you know what happens on a specific hardware platform note that the compiler/optimizer is allowed to assume that signed integer overflow never happens: for example a test like a < a+1 where a is a regular int can be considered always true by a C++ compiler.

like image 115
6502 Avatar answered Nov 01 '22 14:11

6502