Swift: How to use sizeof?

后端 未结 5 1617
逝去的感伤
逝去的感伤 2020-11-29 18:34

In order to integrate with C API\'s while using Swift, I need to use the sizeof function. In C, this was easy. In Swift, I am in a labyrinth of type errors.

I have

相关标签:
5条回答
  • 2020-11-29 18:46

    Swift 3 now has MemoryLayout.size(ofValue:) which can look up the size dynamically.

    Using a generic function that in turn uses MemoryLayout<Type> will have unexpected results if you e.g. pass it a reference of protocol type. This is because — as far as I know — the compiler then has all the type information it needs to fill in the values at compile time, which is not apparent when looking at the function call. You would then get the size of the protocol, not the current value.

    0 讨论(0)
  • 2020-11-29 18:51

    Swift 4

    From Xcode 9 onwards there is now a property called .bitWidth, this provides another way of writing sizeof: functions for instances and integer types:

    func sizeof<T:FixedWidthInteger>(_ int:T) -> Int {
        return int.bitWidth/UInt8.bitWidth
    }
    
    func sizeof<T:FixedWidthInteger>(_ intType:T.Type) -> Int {
        return intType.bitWidth/UInt8.bitWidth
    }
    
    sizeof(UInt16.self) // 2
    sizeof(20) // 8
    

    But it would make more sense for consistency to replace sizeof: with .byteWidth:

    extension FixedWidthInteger {
        var byteWidth:Int {
            return self.bitWidth/UInt8.bitWidth
        }
        static var byteWidth:Int {
            return Self.bitWidth/UInt8.bitWidth
        }
    }
    
    1.byteWidth // 8
    UInt32.byteWidth // 4
    

    It is easy to see why sizeof: is thought ambiguous but I'm not sure that burying it in MemoryLayout was the right thing to do. See the reasoning behind the shifting of sizeof: to MemoryLayout here.

    0 讨论(0)
  • 2020-11-29 18:54

    In Xcode 8 with Swift 3 beta 6 there is no function sizeof (). But if you want, you can define one for your needs. This new sizeof function works as expected with an array. This was not possible with the old builtin sizeof function.

    let bb: UInt8 = 1
    let dd: Double = 1.23456
    
    func sizeof <T> (_ : T.Type) -> Int
    {
        return (MemoryLayout<T>.size)
    }
    
    func sizeof <T> (_ : T) -> Int
    {
        return (MemoryLayout<T>.size)
    }
    
    func sizeof <T> (_ value : [T]) -> Int
    {
        return (MemoryLayout<T>.size * value.count)
    }
    
    sizeof(UInt8.self)   // 1
    sizeof(Bool.self)    // 1
    sizeof(Double.self)  // 8
    sizeof(dd)           // 8
    sizeof(bb)           // 1
    
    var testArray: [Int32] = [1,2,3,4]
    var arrayLength = sizeof(testArray)  // 16
    

    You need all versions of the sizeof function, to get the size of a variable and to get the correct size of a data-type and of an array.

    If you only define the second function, then sizeof(UInt8.self) and sizeof(Bool.self) will result in "8". If you only define the first two functions, then sizeof(testArray) will result in "8".

    0 讨论(0)
  • 2020-11-29 18:57

    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)
    
    0 讨论(0)
  • 2020-11-29 19:08

    Updated for Swift 3

    Be careful that MemoryLayout<T>.size means something different than sizeof in C/Obj-C. You can read this old thread https://devforums.apple.com/message/1086617#1086617

    Swift uses an generic type to make it explicit that the number is known at compile time.

    To summarize, MemoryLayout<Type>.size is the space required for a single instance while MemoryLayout<Type>.stride is the distance between successive elements in a contiguous array. MemoryLayout<Type>.stride in Swift is the same as sizeof(type) in C/Obj-C.

    To give a more concrete example:

    struct Foo {
      let x: Int
      let y: Bool
    }
    
    MemoryLayout<Int>.size      // returns 8 on 64-bit
    MemoryLayout<Bool>.size     // returns 1
    MemoryLayout<Foo>.size      // returns 9
    MemoryLayout<Foo>.stride    // returns 16 because of alignment requirements
    MemoryLayout<Foo>.alignment // returns 8, addresses must be multiples of 8
    
    0 讨论(0)
提交回复
热议问题