在ObjC中,可以通过将bool的位模式转换为UInt8来检索它。
e.g。
然后可以在进一步的位操作操作中使用该位模式。
现在我想在Swift中做同样的事情。
到目前为止我的工作是
UInt8(UInt(boolValue))
但这似乎不是首选方法。
我还需要在O(1)中进行转换,而不需要依赖于数据的分支。因此,不允许使用以下内容。
boolValue ? 1 : 0
此外,是否有一些关于UInt8和UInt初始化程序的实现方式的文档?例如如果要从bool转换的UInt初始值设定项使用数据相关的分支,我也不能使用它。
当然,后备总是使用进一步的按位运算来完全避免bool值(例如Check if a number is non zero using bitwise operators in C)。
答案 0 :(得分:4)
如有疑问,请查看生成的汇编代码:)
func foo(someBool : Bool) -> UInt8 {
let x = UInt8(UInt(someBool))
return x
}
编译为(“ - O”=“编译优化”)
xcrun -sdk macosx swiftc -emit-assembly -O main.swift
给出
.globl __TF4main3fooFSbVSs5UInt8 .align 4, 0x90 __TF4main3fooFSbVSs5UInt8: .cfi_startproc pushq %rbp Ltmp2: .cfi_def_cfa_offset 16 Ltmp3: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp4: .cfi_def_cfa_register %rbp callq __TFE10FoundationSb19_bridgeToObjectiveCfSbFT_CSo8NSNumber movq %rax, %rdi callq __TFE10FoundationSuCfMSuFCSo8NSNumberSu movzbl %al, %ecx cmpq %rcx, %rax jne LBB0_2 popq %rbp retq
可以使用
对函数名进行解码$ xcrun -sdk macosx swift-demangle __TFE10FoundationSb19_bridgeToObjectiveCfSbFT_CSo8NSNumber __TFE10FoundationSuCfMSuFCSo8NSNumberSu _TFE10FoundationSb19_bridgeToObjectiveCfSbFT_CSo8NSNumber ---> ext.Foundation.Swift.Bool._bridgeToObjectiveC (Swift.Bool)() -> ObjectiveC.NSNumber _TFE10FoundationSuCfMSuFCSo8NSNumberSu ---> ext.Foundation.Swift.UInt.init (Swift.UInt.Type)(ObjectiveC.NSNumber) -> Swift.UInt
没有UInt
初始值设定项采用Bool
参数。
所以智能编译器已经使用了Swift之间的自动转换
和基础类型并生成一些代码,如
let x = UInt8(NSNumber(bool: someBool).unsignedLongValue)
两个函数调用可能效率不高。 (而事实并非如此
如果你只有import Swift
,没有基金会就编译。)
现在是假设数据相关分支的另一种方法:
func bar(someBool : Bool) -> UInt8 {
let x = UInt8(someBool ? 1 : 0)
return x
}
汇编代码
.globl __TF4main3barFSbVSs5UInt8 .align 4, 0x90 __TF4main3barFSbVSs5UInt8: pushq %rbp movq %rsp, %rbp andb $1, %dil movb %dil, %al popq %rbp retq
没有分支,只是0x01
的“与”操作!
因此,我没有理由不使用这种“直接”转换。 然后,您可以使用Instruments进行分析,以检查它是否是瓶颈 你的应用。
答案 1 :(得分:2)
@ martin-r的答案更有趣:-),但这可以在游乐场完成。
// first check this is true or you’ll be sorry...
sizeof(Bool) == sizeof(UInt8)
let t = unsafeBitCast(true, UInt8.self) // = 1
let f = unsafeBitCast(false, UInt8.self) // = 0