2

If I have this code:

int A;
unsigned int B;
if (A==B) foo();

the compiler will complain about mixed types in comparison. If I cast A like this:

if ((unsigned int) A==B) foo();

does this instruct the compiler to insert code to convert A from int to unsigned int? Or does it just tell the compiler don't worry about, ignore the type mismatch?


UPDATE: If this is unsafe (as pointed out below), how should I handle this comparison? (Wouldn't assigning the contents of an int to an unsigned int for later comparison also be unsafe)

UPDATE: Wow are there some different answers (from people with thousands of posts). I've accepted what seems like the best, but anyone reading this question should read ALL answers carefully.

TSG
  • 4,242
  • 9
  • 61
  • 121
  • if the compiler complains about mixed types in comparison, it is broken. There is no comparison in the code you show :P – 463035818_is_not_an_ai Mar 23 '16 at 15:45
  • 1
    As @tobi303 points out, you probably mean `==`, as opposed to `=` in your example (that is, equality comparison, not assignment). – TerraPass Mar 23 '16 at 15:49
  • @tobi303 not sure but I believe the hidden comparison is in the if, if(A) -> if(A!=0) – MoonBun Mar 23 '16 at 15:50
  • @Vladp actually, when thinking about it, I also thought that maybe there is a comparison involved, but I would find it strange if the compiler spits out a warning about comparison for this code. – 463035818_is_not_an_ai Mar 23 '16 at 15:53
  • as Schafwolle says in his answer, values are just bits and bytes and the type tells the compiler how to interpret them. afaik, by casting to a different type the value does not change, in contrast to a conversion, that may have to change the value – 463035818_is_not_an_ai Mar 23 '16 at 15:54
  • @TerraPass - you're right I meant ==. Just fixed question – TSG Mar 23 '16 at 15:57
  • @tobi303 - how would I convert from int to unsigned int to ensure the comparison is valid? (Without generating another warning about assigning an int to an unsigned int) – TSG Mar 23 '16 at 16:01
  • you have to check if the int fits into the unsigned type which is not always the case – 463035818_is_not_an_ai Mar 24 '16 at 09:22

5 Answers5

2

When casting, at least at the conceptual level, compiler will create a temporary variable of the type specified in the cast expression.

You may test that this expression:

(unsigned int) A = B; // This time assignment is intended

will generate an error pointing modification of a temporary (const) variable.

Of course compiler is free to optimize away any temporary variables created through a cast. Nevertheless a valid method to build a temporary must exist.

jszpilewski
  • 1,632
  • 1
  • 21
  • 19
1

With plain types, in C and C++, == is always done with both operands converted to the same type. In OP's code, A is converted to unsigned first.

If I cast ... does this instruct the compiler to insert code to convert A from int to unsigned int?

Yes, but that code would have occurred anyway. Without the cast, the compiler is simple warning that it is going to do something that the programmer may not have intended.

Or (If I cast ) does it just tell the compiler don't worry about, ignore the type mismatch?

The type mis-match is not ignored. By supplying the cast, there is no type mis-match to warn about.


How should I handle this comparison?

Insure A is not negative, then convert to unsigned with a cast.

int A;
unsigned int B;
// if (A==B) foo();
if (A >= 0 && (unsigned)A == B) foo();

Every non-negative int can be converted to an unsigned with no value change.

The range of nonnegative values of a signed integer type is a subrange of the corresponding unsigned integer type C11dr §6.2.5 9

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
1

The cast implies a conversion, if necessary. But this is problematic for negative values. They are mapped to positive values on the unsigned type. Thus you have to make sure a negative value never compares equal any (positive) unsigned value:

int A;
unsigned int B;

...

if ( (A >= 0) && (static_cast<unsigned int>(A) == B) )
    foo();

This works because the unsigned variant of an integer type is guaranteed to hold all positive values (including 0) of the corressponding signed type.

Notice the usage of a static_cast instead of the "classic" C-style cast.

Community
  • 1
  • 1
too honest for this site
  • 12,050
  • 4
  • 30
  • 52
0

So you question is just about a signed/unsigned comparison.

C++ standard says in clause 5 Expressions [expr] § 10:

Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follow:
...
Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.

and in 4.7 Integral conversions [conv.integral] §2

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]

That means that on a common system using 2-complement for negative numbers and 32 bits for an int or unsigned int, (unsigned int) -1 will end in 4294967295.

It may be what you want or not, the compiler just warn you that it will consider them as equal.

If it is not what you want, just first test whether the signed value is negative. If it is, say that they are not equal an skip the equality comparison.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
-1

It depends on type of cast and what you are casting. In your particular case nothing is going to happen, but in other cases the actual code will be performed. Simplest example:

void foo(double d) {};
...
int x;
foo(static_cast<double>(x));

In this example there would be code generated.

SergeyA
  • 61,605
  • 5
  • 78
  • 137