views:

430

answers:

8

I have often wondered what exactly does casting do at compiler or machine level. What does it do with the 0 and 1s in memory?

Can anyone point me at some good literature.

+1  A: 

Assuming this is just a reference type cast rather than a conversion (e.g. int to byte), I believe it does the following:

1) Check if the reference is null - if so, quit. 2) Follow the reference to find the object in memory. In the object header, there's information saying what the type is. 3) From the type information, check whether the target type is in the hierarchy. If it's not, throw a ClassCastException with appropriate information.

The "bits" of the result are always the same as the "bits" of the input (assuming there is an output rather than an exception), but then the JVM knows the type of the reference so other operations are guaranteed to succeed.

Jon Skeet
+4  A: 

Casting doesn't modify the individual bits when casting between reference types, it just instructs the compiler/runtime to interpret the bits in a specific way if possible.

If the cast is not possible at compile time due to incompatible types an error is issued. If the cast is not possible at runtime an exception is thrown.

The wiki page on type conversion has additional information.

Brian Rasmussen
This is only true for non-numeric casts
Aaron Digulla
The class cast exception check must be inserted into the byte code somehow, surely?
Bill Michell
+1  A: 

It depends on what you cast. For numeric casts, (float to int and back), the CPU will try to find the closest number which fits into the destination.

For type cases, it doesn't do anything to memory. It's just a way for the software developer to tell the stupid compiler that some variable for once should be treated as if it was of a different type.

I tried to google some informations about rules for numeric casting but there isn't much around. You can try the C99 standard but I'm not sure whether it will overwhelm you. IIRC, the rules are:

  • Casting down (big type -> smaller type like double -> float -> int -> byte) will cut off information which can't be represented (so double->float will lose precision, -> int will lose all decimal places + no rounding).

  • Casting up (smaller type -> bigger type) means to fill the additional bits with '0'.

Of course, there are numbers which you can't really represent (like 0.1). Any operation on these even without casting will lose information (which is why 0.1*10 can be != 1.0).

Aaron Digulla
+1  A: 

In C for non numeric types, casting does nothing on 0 and 1s in memory.

For numeric types, the C compiler makes conversion so that numeric value remains the same, as much as possible.

If you do want to cast numeric types without changing bit values, you have to use a union or cast pointers (following code illustrates the latter):

float a;
int b = 3;

a = *((float*)&b);
mouviciel
+2  A: 

Regarding Casting, a useful literature would be the JavaTM Virtual Machine Specification.

At the section Conversions and Promotions, you would see there is six broad kinds of conversions:

  • Identity conversions
  • Widening primitive conversions
  • Narrowing primitive conversions
  • Widening reference conversions
  • Narrowing reference conversions
  • String conversions

There are five conversion contexts in which conversion expressions can occur, including the Casting Conversion:

Casting contexts allow the use of:

  • an identity conversion,
  • a widening primitive conversion,
  • a narrowing primitive conversion,
  • a widening reference conversion, or
  • a narrowing reference conversion.

Thus, casting conversions are more inclusive than assignment or method invocation conversions: a cast can do any permitted conversion other than a string conversion.

Casting can convert a value of any numeric type to any other numeric type. A value of type boolean cannot be cast to another type. A value of reference type cannot be cast to a value of primitive type.

Some casts can be proven incorrect at compile time and result in a compile-time error. Otherwise, either the cast can be proven correct at compile time, or a runtime validity check is required. (See The JavaTM Language Specification for details.)
If the value at run time is a null reference, then the cast is allowed. If the check at run time fails, a ClassCastException is thrown.

VonC
A: 

See this current question:

http://stackoverflow.com/questions/674982/performance-hit-from-c-style-casts

anon
+1  A: 

One needs to also understand how references work at both compile and runtime time.

Each and every type holds a lookup table for each and every method which resolves each method to the most resolved method for that type.

So if your reference is a Object calling toString() does the right thing and finds the most derived toString() method. Casting is necessary to allow the runtime to guarantee that any given reference really has target methods for each method exposed on the reference. After passing the cast from X to Y any reference of type Y can be assured that all its methods are available on the casted(sp) reference.

mP
+1  A: 

Others have covered the basics, but I'd like to say a few words about how a compiler is implemented that may be enlightening in his case.

The compiler maintains a list (called the symbol table) of variable names in use at any particular point in the program and some information about the variables. The list of information includes:

  • their assigned storage (in this register, at that memory location, etc...)
  • what type they are (i.e. integer or string or SubWhatsitObj) including any restriction (like for instance constantness)
  • any linkage information the compiler needs

The compiler uses this information to decide how to treat expressions involving the variables. The kind of meta-information that is stored in the symbol table can also be derived for any expression from it's components.

Except in the special case of numeric type conversion, a cast just tells the compiler to use different meta-information for a variable or expression than would usually be the case. No bits in memory are affected at all, but the outcome of a calculation may be.

dmckee