12
void fun(){
    signed int a=-5;
    unsigned int b=-5;
    printf("the value of b is %u\n",b);
    if(a==b)
         printf("same\n");
    else
         printf("diff");
}

It is printing :

4294967291

same

In the 2nd line signed value is converted to unsigned value. So b has the value UINTMAX + 1 - 5 = 4294967291.

My question is what is happening in the comparison operation .

1) Is a again converted to unsigned and compared with b ?

2) Will b(ie unsigned ) be ever casted to signed value and compared automatically?

3) Is conversion from unsigned to signed undefined due to int overflow ?

I have read other posts on the topic. I just want clarification on questions 2 and 3 .

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
hackrock
  • 317
  • 1
  • 4
  • 13
  • partially answered here http://stackoverflow.com/a/2262746/532208 – triclosan Feb 29 '12 at 11:32
  • this link clears my question 2. – hackrock Feb 29 '12 at 11:39
  • Please be aware that these questions are not related to each other. There are two issues here: what happens when signal and unsigned types are mixed in the same operation, and what happens when you try to store a signed int inside an unsigned int. – Lundin Feb 29 '12 at 12:11

3 Answers3

21

1) Is a again converted to unsigned and compared with b ?

Yes. In the expression (a==b), the implicit type conversion called "balancing" takes place (the formal name is "the usual arithmetic conversions"). Balancing rules specify that if a signed and a unsigned operand of the same size and type are compared, the signed operand is converted to a unsigned.

2) Will b(ie unsigned ) be ever casted to signed value and compared automatically?

No, it will never be converted to signed in your example.

3) Is conversion from unsigned to signed undefined due to int overflow ?

This is what the standard says: (C11)

6.3.1.3 Signed and unsigned integers

1 When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.

2 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.

3 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

In other words, if the compiler can manage to do the conversion in 2) above, then the behavior is well-defined. If it cannot, then the result depends on the compiler implementation.

It is not undefined behavior.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    @rocky To prevent possible misunderstandings: in point 2), with "in your example", Lundin meant that an `unsigned int` is never automatically cast to `int` for a conversion. If you compare a 4-byte `unsigned int` to an 8-byte `long long int`, the unsigned value is automatically converted to the larger signed type. – Daniel Fischer Feb 29 '12 at 14:04
  • @DanielFischer But there is no long long int in the question... Anyway, the best thing to do is to read up on the [usual arithmetic conversions](http://stackoverflow.com/questions/7544123/c-usual-arithmetic-conversions) and their sub-rule called the [integer promotion rules](http://stackoverflow.com/questions/7711124/why-are-the-results-of-integer-promotion-different). It is mandatory knowledge for any C programmer. – Lundin Feb 29 '12 at 14:19
  • Yes, but "Will b ever be cast to a signed value ... automatically" might refer to more general situations, so I thought it could be beneficial to make clear what "in your example" means, just in case. – Daniel Fischer Feb 29 '12 at 14:24
  • This could be worded better... certainly an unsigned short, char can be converted to signed, but it is never converted to a *negative* value. – Antti Haapala -- Слава Україні Oct 12 '20 at 15:08
  • @AnttiHaapala What do you mean? Of course it can be converted to a negative value. `unsigned char a = 0xFF; signed char b = a; printf("%d\n", b);`. Prints `-1` on all compilers I know of, even though it's technically impl.defined. – Lundin Oct 13 '20 at 07:05
  • @Lundin ah I mean by promotions and usual arithmetic conversions. They would not convert unsigned value to negative. – Antti Haapala -- Слава Україні Oct 13 '20 at 08:33
  • @AnttiHaapala I don't see what any of that has to do with this very old post. Better posts have been written since this one: [Implicit type promotion rules](https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules). – Lundin Oct 13 '20 at 10:29
2

Answers:

  1. a is converted to unsigned int.
  2. If a had a wider range than the signed counterpart of b (I can imagine long long a would do), b would be converted to a signed type.
  3. If an unsigned value can't be correctly represented after conversion to a signed type, you'll have implementation-defined behavior. If it can, no problem.
Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
  • I have flagged the comment above as "no longer needed", because meanwhile, someone has edited the answer to address the issue mentioned in the comment. Therefore, as far as I can tell, the comment is now redundant/outdated. – Andreas Wenzel Jun 27 '23 at 03:49
-3
b = -5;

That counts as overflow and is undefined behavior. Comparing signed with unsigned automatically promotes the operands to unsigned. -In case of overflow, you'll find yourself again in a case of undefined behavior.- plain wrong, see [edit] below

See also http://c-faq.com/expr/preservingrules.html.

[edit] Correction - the standard does state that the 2 complement should be used when converting from negative signed to unsigned.

foxx1337
  • 1,859
  • 3
  • 19
  • 23
  • 5
    No, `b = -5;` is defined. The standard explicitly states that conversions from signed to unsigned don't overflow and give you the value modulo `UTYPE_MAX + 1`. – Daniel Fischer Feb 29 '12 at 11:36
  • @DanielFischer: they do "overflow", but don't cause UB. – Alexey Frunze Feb 29 '12 at 11:38
  • 3
    @Alex As far as I gathered, in standardese, overflow doesn't refer to the well defined wrapping of unsigned integers, cf. "An example of undefined behavior is the behavior on integer overflow" in 3.4.3. Of course in everyday speech, it is called overflow too. – Daniel Fischer Feb 29 '12 at 11:45