Swift: How to use sizeof?
Use sizeof as follows:
let size = sizeof(Int)
sizeof
uses the type as the parameter.
If you want the size of the anInt
variable you can pass the dynamicType
field to sizeof
.
Like so:
var anInt: Int = 5
var anIntSize: Int = sizeof(anInt.dynamicType)
Or more simply (pointed out by user102008):
var anInt: Int = 5
var anIntSize: Int = sizeofValue(anInt)
Swift use sizeof with Int32 Array
You can get the number of elements in an array simply with
let count = testArray.count
and the total number of bytes of its elements with
var arrayLength = testArray.count * sizeof(Int32)
// Swift 3:
var arrayLength = testArray.count * MemoryLayout<Int32>.size
sizeof
is used with types and sizeofValue
with values, so both
var arrayLength = sizeof([Int32])
var arrayLength = sizeofValue(testArray)
would compile. But that gives you the size of the struct Array
, not the size
of the element storage.
Use of unresolved identifier 'sizeof'
I would rewrite your code in Swift 4 as:
var positionToSend = car.position
let dataSend = Data(bytes: &positionToSend, count: MemoryLayout.size(ofValue: positionToSend))
do {
try match.sendData(toAllPlayers: dataSend, with: .unreliable)
} catch {
//Write code for `if error != nil`...
print(error)
}
You do not need withUnsafePointer
.
In Swift, how to get the true size of an `Any` variable?
I'll begin with some technical details about the limitations of Any
in this case.
So, what is Any
? It's an empty protocol to which every type implicitly conforms to.
And how does the compiler represent variables of protocol types? It's by wrapping the actual value in an existential container. So basically when you're referencing a variable of this kind, you're actually talking to the container (well, actually not you, but the compiler is :).
An existential container has a layout that can be represented like this C structure:
struct OpaqueExistentialContainer {
void *fixedSizeBuffer[3];
Metadata *type;
WitnessTable *witnessTables[NUM_WITNESS_TABLES];
};
The container elements are greatly explained in this document, I'll also try to summarize them here:
fixedSizeBuffer
either holds the whole value, if it takes less than 24 bytes, or holds a pointer to a heap allocated zone, containing the valuetype
is a pointer to the type metadatawitnessTables
is what makes this layout occupy various sizes, as the number of protocol witness tables can vary from zero to virtually any number of protocols.
So, with the above in mind:
Any
needs no witness tables, thus it occupies 32 bytes- a single protocol variable occupies 40 byes
- a composed protocol variable occupies 32 + N*8, where N is the number of "independent" protocols involved in the composition
Note that the above is true if there are no class protocols involved, if a class protocol is involved, then the existential container layout is a little bit simplified, this is also better described in the linked document from above.
Now, back to the problem from the question, it's the existential container created by the compiler the one which prevents you from accessing the actual type. The compiler doesn't make this structure available, and transparently translates any calls to protocol requirements to dispatches through the witness tables stored in the container.
But, might I ask you, why are you circulating Any
? I assume you don't want to handle all possible and future types in a generic manner. A marker protocol might help here:
protocol MemoryLayouted { }
extension MemoryLayouted {
var memoryLayoutSize: Int { MemoryLayout.size(ofValue: self) }
}
Then all you have left to do is to add conformance for the types you want to support:
extension Int: MemoryLayouted { }
extension String: MemoryLayouted { }
extension MyAwesomeType: MemoryLayouted { }
With the above in mind, you can rewrite your initial code to something like this:
let regularInt: Int = 1
let anyInt: MemoryLayouted = 2
print(regularInt.memoryLayoutSize) // 8
print(anyInt.memoryLayoutSize) // 8
You get consistent behaviour and type safety, a type safety that might translate to a more stable application.
P.S. A hacky approach, that allows you to use Any
, might pe possible by unpacking the existential container via direct memory access. The Swift ABI is stable at this point, so the existential container layout is guaranteed not to change in the future, however not recommending going that route unless absolutely necessary.
Maybe someone that stumbles this question and has experience in the ABI layout code can provide the code for it.
Get the size (in bytes) of an object on the heap
One option on Apple platforms, because Swift classes are currently built on top of Objective-C classes there, would be to use the Obj-C runtime function class_getInstanceSize
, which gives you the size in bytes of an instance of the class, including any padding.
// on a 64-bit machine (1 word == 8 bytes)...
import Foundation
class C {}
print(class_getInstanceSize(C.self)) // 16 bytes metadata for empty class
// (isa ptr + ref count)
class C1 {
var i = 0
var i1 = 0
var b = false
}
print(class_getInstanceSize(C1.self)) // 40 bytes
// (16 metadata + 24 ivars, 8 for i + 8 for i1 + 1 for b + 7 padding)
sizeof() gives an error for array argument
You can iterate through the array like this:
let graphPoint = // ...
var radius = CGFloat(0.0)
for a in graphPoint {
let b = sqrt(pow(a.x - point.x, 2.0) + pow(a.y - point.y, 2.0))
if b > radius {
radius = b
}
}
I often have this error "operator X cannot be applied to two Y operands", and usually the problem comes from somewhere else, in this particular case it's because Swift sizeof
uses the type and not the var as Glenn said.
Size of struct with optionals in swift
Int?
aka Optional<Int>
is an enum
type and requires 9 bytes: 8 bytes for the integer (if we are on a 64-bit platform) plus one byte for the case discriminator.
In addition, each integer is aligned in memory to its natural (8 byte) boundary, by inserting padding bytes.
So your struct would look like this in memory:
i1 i1 i1 i1 i1 i1 i1 i1 // 8 bytes for the first integer
c1 p1 p1 p1 p1 p1 p1 p1 // 1 byte for the first case discriminator,
// ... and 7 padding bytes
i2 i2 i2 i2 i2 i2 i2 i2 // 8 bytes for the second integer
c2 p2 p2 p2 p2 p2 p2 p2 // 1 byte for the second case discriminator
// ... and 7 padding bytes
i3 i3 i3 i3 i3 i3 i3 i3 // 8 bytes for the third integer
c3 // 1 byte for the third case discriminator
That makes a total of 41 bytes.
If SampleStruct
values are stored contiguously in an array then additional padding is inserted between the elements to ensure that each value starts on a 8-byte boundary. This additional padding is taken into account by the stride:
print(MemoryLayout<SampleStruct>.size) // 41
print(MemoryLayout<SampleStruct>.stride) // 48
You can find the gory details in the Type Layout document of the Swift documentation.
Related Topics
Index of a Substring in a String With Swift
How to Get Ip Address in Swift
How to Add Type Constraints to a Swift Protocol Conformance Extension
Trying to Understand Asynchronous Operation Subclass
Difference Between a Weak Reference and an Unowned Reference
Swift 2 - Unsafemutablepointer≪Void≫ to Object
Swiftui: How to Make Textfield Become First Responder
Waiting Until the Task Finishes
Passing an Array to a Function With Variable Number of Args in Swift
How to Enumerate an Enum With String Type
How to Make a Weak Protocol Reference in 'Pure' Swift (Without @Objc)
Opt Out of Uiscenedelegate/Swiftui on Ios
How to Update the Constant Height Constraint of a Uiview Programmatically
Get Nth Character of a String in Swift Programming Language