A very similar question was answered on this list by Ian Lance Taylor on
3/24/2010. He wrote:
The C99 standard says that when converting floating point to integer,
the value is first truncated toward zero. If the value of the
integral part cannot be represented by the integer type, the behaviour
is undefined. This means that converting a negative floating point
value<= -1.0 to an unsigned integer type is undefined, and the code
may act unpredictably.
In your code, casting to a double yields 52536.0. Since this is not in
the range -32768 to +32767 the cast to short int is undefined. So all
bets are off.
I responded on 3/29:
I think this is a good illustration of why one should not use type
casting to perform algorithmic operations. You should operate on the
data and test the resulting value to ensure it will fit within the new
type.
I'm a big fan of writing code that explicitly shows each step in an
algorithm one statement at a time. If the operations are in a loop, and
testing shows that the loop is slowing things down too much, then
obscure and tricky code may be in order, but only with good commenting.
The maintenance programmer, perhaps you at a later date, will appreciate
being able to follow simple code.
--Bob
On 4/14/2010 11:31 AM, Gederberg, Thomas K wrote:
I am having an interesting problem when casting from double to an unsigned short int as shown in the following example:.
#include<stdio.h>
int main()
{
unsigned short int ius;
unsigned short int ous;
short int is;
ius = 52536;
is = (short int) ((double)(ius));
ous = (unsigned short int) is;
printf("ius = %hu\n", ius);
printf("is = %d\n", is);
printf("ous = %hu\n", ous);
}
Using a Sun CC compiler and Microsoft Visual C++ for 32-bit, the above code generates:
ius = 52536
is = -13000
ous = 52536
which is as I would expect. The two's complement of 52536 is -13000.
However, when compied using gcc (version 3.2.3, also confirmed with gcc 4.4.1) with the -m32 option specifed, the code produces:
ius = 52536
is = -32768
ous = 32768
Is this a bug with gcc? Also, if I don't cast ius to (double) before casting to (short int), I get what I expect. Can anyone explain?
Thanks!
Note: this problem popped up in some code I am trying to port from Solaris to Linux. The code includes the following macro:
#define REAL_TO_SHORT_BIT_TYPE(X) ((unsigned short int) ((short int) ((double) (x))))