T.T.T.
T.T.T.

Reputation: 34593

How does casting to "signed int" and back to "signed short" work for values larger than 32,767?

Code:

typedef signed   short  SIGNED_SHORT;   //16 bit
typedef signed   int    SIGNED_INT;     //32 bit


SIGNED_SHORT x;

x = (SIGNED_SHORT)(SIGNED_INT) 45512; //or any value over 32,767

Here is what I know:

Signed 16 bits:
Signed: From −32,768 to 32,767
Unsigned: From 0 to 65,535

Don't expect 45512 to fit into x as x is declared a 16 bit signed integer.

How and what does the double casting above do?

Thank You!

Upvotes: 2

Views: 2499

Answers (4)

Keith Thompson
Keith Thompson

Reputation: 263547

typedef signed   short  SIGNED_SHORT;   //16 bit
typedef signed   int    SIGNED_INT;     //32 bit

These typedefs are not particularly useful. A typedef does nothing more than provide a new name for an existing type. Type signed short already has a perfectly good name: "signed short"; calling it SIGNED_SHORT as well doesn't buy you anything. (It would make sense if it abstracted away some information about the type, or if the type were likely to change -- but using the name SIGNED_SHORT for a type other than signed short would be extremely confusing.)

Note also that short and int are both guaranteed to be at least 16 bits wide, and int is at least as wide as short, but different sizes are possible. For example, a compiler could make both short and int 16 bits -- or 64 bits for that matter. But I'll assume the sizes for your compiler are as you state.

In addition, signed short and short are names for the same type, as are signed int and int.

SIGNED_SHORT x;

x = (SIGNED_SHORT)(SIGNED_INT) 45512; //or any value over 32,767

A cast specifies a conversion to a specified type. Two casts specify two such conversions. The value 45512 is converted to signed int, and then to signed short.

The constant 45512 is already of type int (another name for signed int), so the innermost cast is fairly pointless. (Note that if int is only 16 bits, then 45512 will be of type long.)

When you assign a value of one numeric type to an object of another numeric type, the value is implicitly converted to the object's type, so the outermost cast is also redundant.

So the above code snippet is exactly equivalent to:

short x = 45512;

Given the ranges of int and short on your system, the mathematical value 45512 cannot be represented in type short. The language rules state that the result of such a conversion is implementation-defined, which means that it's up to each implementation to determine what the result is, and it must document that choice, but different implementations can do it differently. (Actually that's not quite the whole story; the 1999 ISO C standard added permission for such a conversion to raise an implementation-defined signal. I don't know of any compiler that does this.)

The most common semantics for this kind of conversion is that the result gets the low-order bits of the source value. This will probably result in the value -20024 being assigned to x. But you shouldn't depend on that if you want your program to be maximally portable.

Upvotes: 5

David
David

Reputation: 28188

The double casting is equivalent to:

short x = static_cast<short>(static_cast<int>(45512));

which is equivalent to:

short x = 45512;

which will likely wrap around so x equals -20024, but technically it's implementation defined behavior if a short has a maximum value less than 45512 on your platform. The literal 45512 is of type int.

Upvotes: 4

Dietrich Epp
Dietrich Epp

Reputation: 213638

When you cast twice, the casts are applied in sequence.

int a = 45512;
int b = (int) a;
short x = (short) b;

Since 45512 does not fit in a short on most (but not all!) platforms, the cast overflows on those platforms. This will either raise an implementation-defined signal or result in an implementation-defined value.

In practice, many platforms define the result as the truncated value, which is -20024 in this case. However, there are platforms which raise a signal, which will probably terminate your program if uncaught.

Citation: n1525 §6.3.1.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.

Upvotes: 5

eq-
eq-

Reputation: 10096

You can assume it does two type conversions (although signed int and int are only separated once in the C standard, IIRC).

If SIGNED_SHORT is too small to handle 45512, the result is either implementation-defined or an implementation-defined signal is raised. (In C++ only the former applies.)

Upvotes: 2

Related Questions