-
-
Save acalism/038ec994bdcc1baf23deecb79e80a8fc to your computer and use it in GitHub Desktop.
A Quick Overview of Unsafe Bit Cast
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Let's declare two structs that with different variables and different boolean values: | |
struct A { | |
let x = true | |
} | |
struct B { | |
let y = false | |
} | |
// We're going to create an instance of A and cast it into an instance of B. | |
let ourA = A() | |
let ourB = unsafeBitCast(ourA, B.self) | |
// Now, what do you think ourB.y will have the value of? | |
// Will it even exist since the A we instantiated only have a variable x, not y? | |
println(ourB.y) // -> true | |
// It turns out it's ture--how can that be?! | |
// Well, when we cast ourA from type A to B, nothing actually changes except how we interpret it. | |
// When we check x or y, the compiler converts this to code that returns the first sizeof(Bool) | |
// bytes of our struct as a Bool value. Casting from A to B doesn't change the value of these bytes, | |
// which were already set to true. Further, it doesn't matter that A has no y property because ourB | |
// is interpreted as type B, and Swift simply returns the first sizeOf(Bool) bytes when y is accessed | |
// from any type B. | |
// Note that, if we add more properties to each, the must have the same size and be aligned to accomplish | |
// this same sort of thing. A struct with a Bool and an Int is simply sizeof(Bool) bytes of memory followed | |
// by sizeof(Int) bytes of memory. When we access the Int, Swift simply skips the first sizeof(Bool) bytes | |
// and accesses the Int's bytes. Note that this is the same way structs are represented in C too! | |
// Now that you think you understand everything, let's change it up a little. | |
// We will now define x and y as static types on A and B. | |
struct A { | |
static let x = true | |
} | |
struct B { | |
static let y = false | |
} | |
// We again do our cast and something strange happens... | |
let ourA = A() | |
let ourB = unsafeBitCast(ourA, B.self) | |
println(ourB.dynamicType.y) // -> false | |
// It's... false?!?! | |
// Yup. Remember that ourB is interpreted as type B even if its internal representation is of type A. | |
// That doesn't matter though. DynamicType refers to the actual type of the object as represented under | |
// Swift's runtime. That mean that static methods, or methods on a Type, will work as they normally would | |
// for whatever type you casted your object into. | |
// Pretty cool, huh? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment