We came across a very strange behavior with a code like this (this is a simplified version; it took quite a time before we were able to identify a similar problem in our code):

unsigned int x = 10;
int a = ((int-1) * x;
int b = ((int)-1) * x / 2; // [B]Result is not -5!!!!![/B]
assert(a == -10); // OK
assert(a == -5);   //[B] Assert fails!!!!![/B]

Program was compiled with the Visual Studio 2008. Can anybody explain why 'b' is not -5? It seems like 'b' is treated as unsigned int instead of int.

mvmalderen commented: For trying to use code tags on first post. +7

Recommended Answers

All 4 Replies

Member Avatar for jencas

1.
int a = ((int-1) * x; // this does not compile!!!!

2.
assert(a == -5); // Assert fails!!!!!

Does assert(b == -5); work??

int a = ((int-1) * x; I suppose you meant int a = ((int)-1) * x; assert(a == -5); // Assert fails!!!!!
I suppose you meant assert(b == -5); // Assert fails!!!!!

From TCPL K&R 2nd ed, if either operand of an arithmetic operation is unsigned int, the other is also converted to unsigned int and the result is also an unsigned int. (I'm only assuming the case where both are same width, e.g. unsigned int against signed int).

consider int b = ((int)-1) * x / 2; which is actually int b =( ((int)-1) * x )/ 2; if you care for the left associativity of the multiplication operator.
((int)-1) yields a integer -1 (note that this cast is useless). Since it is being multiplied by a unsigned int, -1 is promoted to a unsigned int. Any negative int when promoted to int will yield smallest non-negative value that is congruent to that integer, modulo one more than the largest value that can be represented in the unsigned type. So it is a very large number(4294967286 on my machine)which when multiplied by 10 yields larger number which is again demoted to fit into a unsigned int. Now you divide that number by two and you get the result.(which is still a larger number)(2147483643 on my machine.
The funny part is: all this doesn't happens in the line previous to this. That is perhaps because of your compiler's smartness, it doesn't promote -1 to int but demotes x to a int. This is done as, there is no more operation to perform.
Anyways., the correct procedure would be ((int)-1) * (x / 2); which would yield the desired result.
Note that int(-1) is same as -1.

If I were you I would have chosen a statement like this: int b = ( int(x)*(-1) ) /2; The code tags are : [code=cplusplus] //code goes here

[/code]

This is C++ not C, so I would have written:

b= -1*static_cast<int>(x)/2;

The main advantage of this is the you have an explicit bracket around the section you are casting and it is a BIG flag that you are changing type. Something that in numerical code is often such a big area of problems that the old (type) casts are often forbidden.

It also avoids nasty stuff when you convert (accidentally) from a pointer to a numeric type. Easily done when you have a long expression with pointers and multiplications.

The funny part is: all this doesn't happens in the line previous to this. That is perhaps because of your compiler's smartness, it doesn't promote -1 to int but demotes x to a int.

1. Probably you mean doesn't promote -1 to unsigned int...
2. All this happens in int a = (int)-1 * x . The funny part is: (int)-1 is the same as -1 because an integer literal already (and always) has int type. The compiler never takes into account left part type: it promotes -1 to unsigned int (max value) then multiply it to unsigned(10) (ignores integer overflow). After that the result is unsigned(4294967286) or int(-10) - the same bit pattern...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.