开发者

Question about unsigned int in c [duplicate]

开发者 https://www.devze.com 2023-03-08 19:11 出处:网络
This question already has answers here: Closed 11 years ago. Possible Duplicate: unsigned int and signed char comparison
This question already has answers here: Closed 11 years ago.

Possible Duplicate:

unsigned int and signed char comparison

int j = 10;
unsigned int i = 10;
if( j > -1 )
    printf("1\n");
else
    printf("2\n");
if( i > -1 )
    printf("3\n");
else
    printf("4\n");

The output is :

1
4

I've traced into the assembly and the comparation is similar:

cmp     dword ptr [ebp-10h],0FFFFFFFFh
...
cmp     dword ptr [ebp-14h],0FFF开发者_开发问答FFFFFh

But still don't understand why one is true and the other is false.

IMO the cpu have no idea whether dword ptr is signed or not.

So how does it work under the hood?

UPDATE

anyone can explain it in assembly level?


As the other answers say, -1 is being converted to unsigned int. Check the jump instructions that follow. One should be "ja" and the other "jg": the unsigned and signed jump instructions.


In the following code:

if( i > -1 )
    printf("3\n");
else
    printf("4\n");

the -1 is converted to an unsigned int, which is the biggest unsigned int and clearly larger than 10.

On my machine the following code

#include <stdio.h>
int main()
{
  unsigned int i = -1;
  printf("%u\n", i);
  return 0;
}

Yields: 4294967295


When comparing unsigned (i.e i) with signed (i.e -1) the compiler converts the signed value to unsigned.

Converting -1 to unsigned would give a very large value and so the ( i > -1) condition would yield false.

[6.3.1.3/2] (C99)

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.


Here is your program annotated with all implicit casts it contains:

  int j;
  unsigned int i;
  j = 10;
  i = (unsigned int)10;
  if (j > -1) { printf("1\n"); }
  else { printf("2\n"); }
  if (i > (unsigned int)-1) { printf("3\n"); }
  else { printf("4\n"); }

The first comparison is a comparison of signed ints. The second one is a comparison of unsigned ints.

Regarding the other aspect of your question, there is indeed only one comparison instruction in assembly, but it sets various flags. You test the flag you are interested in for the comparison you are doing (signed, unsigned,...).


As @Neil G points out, while cmp doesn't know about unsigned vs signed, the conditional jump instructions do.

This is done this way because normal arithmethic instructions (like sub) affect all the relevant condition codes, so then you can do a conditional jump directly, without needing to do any explicit comparison.

Note that cmp is just a sub that doesn't affect the destination.


Before the ">" operator can be evaluated, the operands on both sides need to be (conceptually) converted to the same type. In this case (not sure if it's "standard", or just the whim of the compiler) the -1 is converted to unsigned. -1 is, of course, 0xFFFFFFFF, and that's larger, in an unsigned compare, than 0x0000000A, though in a signed compare it's smaller (because the high-order bit is the sign bit, and signed negative numbers are almost always represented in "twos-complement").

"Under the hood" I suspect that on your CPU the resulting condition code has both signed and unsigned sections, and the difference between the two results has to do with how the condition code is checked, rather than the compare itself.


When you compare an unsigned int and a signed int, the signed int is converted to unsigned int. Converting a negative signed int to a unsigned int is done by adding UINT_MAX + 1.

So -1 is converted to UINT_MAX + 1 - 1 = UINT_MAX which is superior to 10.

See also What's the difference between the "unsigned preserving" and "value preserving" rules?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号