Home > Net >  С typecasting in conditions
С typecasting in conditions

Time:10-22

There is a simple example:

unsigned a = -5;
int b = 5;
if (a   b <= -1){
...
}

To which type will cast a b? To signed or unsigned? And is it noted in C-standard or compiler will decide what to do?

CodePudding user response:

Due to the usual arithmetic conversions if two objects have the same rank then an object of signed integer type is converted to the unsigned integer type.

From the C Standard (6.3.1.8 Usual arithmetic conversions)

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

and (6.5.8 Relational operators)

3 If both of the operands have arithmetic type, the usual arithmetic conversions are performed.

So in this condition

if (a   b <= -1){

the both operands a b and -1 are converted to the type unsigned int.

That is as a has the type unsigned int then and the expression a b also has the type unsigned int. As the expression a b has the type unsigned int then and the expression -1 will also have the type unsigned int (-1 will be converted to the maximum value of the type unsigned int).

Thus the condition of the if statement will evaluate to the logical true.

CodePudding user response:

Firstly, be careful of your terminology:

To which type will cast a b?

A cast is an explicit conversion (eg (int)(a))... this is an implicit conversion!

But isn't C a great language...

Consider:

unsigned a = -5;

Any sensibly defined language would throw an error, when assigning a negative number to an unsigned variable...

Consider, further ( unsigned int signed int ): the OP is not the first, nor will be the last, to get confused by the implicit type promotions in the C language - some of which are even less obvious than this... the answer is that this will result in an unsigned int (unsigned signed = signed).

Then the potential Heisenbug (and/or maybe a Schrodinger's Bug):

if ( unsigned int <= -1 )

By definition, an unsigned integer cannot be less than zero, so the resultant IF clause is unreachable, and may well be optimised away. However, the -1 will be actually be promoted to an unsigned integer as UINT_MAX and therefore this becomes if ( unsigned int <= UINT_MAX ), which of course is always true, and you have an unconditional conditional.

Of course, you might not really care whether this is unconditionally true, unconditionally false, or the wrong answer...

But most of the time, this matters... So, how do you protect yourself?

MISRA C introduces the concept of the Essential Type Model, which has guidelines to protect you from unexpected type conversions - Section 8.10 of the book (including a number of Rules) plus two appendices.

Edit: <= not just < as per the OP ;-)

(see profile for affiliation)

  • Related