Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why C compiler cannot do signed/unsigned comparisons in an intuitive way [closed]

By "intuitive" I mean given

int a = -1;
unsigned int b = 3;

expression (a < b) should evaluate to 1.

There is a number of questions on Stackoverflow already asking why in this or that particular case C compiler complains about signed/unsigned comparison. The answers boil down to integer conversion rules and such. Yet there does not seem to be a rationale behind why compiler has to be so exceptionally dumb when comparing singed and unsigned integers. Using declarations above, why expression like

(a < b)

is not automatically substituted by

(a < 0 || (unsigned int)a < b)

if there is no single machine instruction to do it properly?

Now, there have been some comments for previous questions in the vein of "if you have to mix signed and unsigned integers, there is something wrong with your program". I would not buy that since libc itself makes it impossible to live in a signed-only or unsigned-only world (e.g. example sprintf() family of functions returns int as the number of bytes written, send() returns ssize_t and so on).

I also don't think I can buy an idea expressed in comments below that implicit conversion of signed integer to unsigned in comparison (the (d - '0' < 10U) "idiom") bestows some additional powers on C programmer compared to explicit cast (((unsigned int)(d - '0') < 10U)). But sure enough it opens wide opportunities to screw up.

And yes, I'm happy that compiler warns me that it cannot do it (unfortunately only if I ask it explicitly). The question is - why can't it? Usually there are good reasons behind standard's rules, so I'm wondering if there are any here?

like image 605
ayurchen Avatar asked Jan 23 '13 17:01

ayurchen


People also ask

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.

Can signed variables be converted to unsigned variables in C?

To convert a signed integer to an unsigned integer, or to convert an unsigned integer to a signed integer you need only use a cast. For example: int a = 6; unsigned int b; int c; b = (unsigned int)a; c = (int)b; Actually in many cases you can dispense with the cast.

Is it suggested to compare signed and unsigned numbers in C++?

then your compiler may issue a warning like "comparison between signed and unsigned integer expressions". Briefly, the problem is that a standard C++ compiler will handle this code by casting x as an unsigned int before doing the comparison, which may turn a negative number into a large positive number.

What is the difference between unsigned and signed in C?

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.


1 Answers

The automatic replacement cannot be made because that's different from C semantics, and would horribly break programs that use the conversion correctly. For example:

if (d-'0'<10U)  // false if d is not a digit

would become true for ASCII space and many other characters with your proposed replacement.

By the way, I believe this question is partly a duplicate of:

Would it break the language or existing code if we'd add safe signed/unsigned compares to C/C++?

like image 145
R.. GitHub STOP HELPING ICE Avatar answered Oct 27 '22 00:10

R.. GitHub STOP HELPING ICE