Skip to content

Instantly share code, notes, and snippets.

@acalism
Forked from JadenGeller/Unsafe Bit Cast.swift
Created December 25, 2017 12:10
Show Gist options
  • Save acalism/038ec994bdcc1baf23deecb79e80a8fc to your computer and use it in GitHub Desktop.
Save acalism/038ec994bdcc1baf23deecb79e80a8fc to your computer and use it in GitHub Desktop.
A Quick Overview of Unsafe Bit Cast
// 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