在 Swift 中获取 bool 的位模式

Eta*_*tan 2 int boolean bit-manipulation type-conversion swift

在 ObjC 中,可以通过将 bool 类型转换为 UInt8 来检索 bool 的位模式。

例如

  • 真=> 0x01
  • 假=> 0x00

然后可以将该位模式用于进一步的位操作操作。


现在我想在 Swift 中做同样的事情。

到目前为止我所做的工作是

UInt8(UInt(boolValue))
Run Code Online (Sandbox Code Playgroud)

但这看起来并不是首选方法。

我还需要 O(1) 内的转换,而不需要依赖于数据的分支。所以,像下面这样的东西是不允许的。

boolValue ? 1 : 0
Run Code Online (Sandbox Code Playgroud)

另外,是否有一些关于 UInt8 和 UInt 初始值设定项实现方式的文档?例如,如果从 bool 转换的 UInt 初始值设定项使用数据相关分支,我也无法使用它。

当然,后备方法始终是使用进一步的按位运算来完全避免 bool 值(例如,使用 C 中的按位运算符检查数字是否非零)。


  • Swift 是否提供了一种优雅的方式来访问 Bool 的位模式/将其转换为 UInt8,时间复杂度为 O(1),无需数据依赖分支?

Mar*_*n R 5

如有疑问,请查看生成的汇编代码:)

func foo(someBool : Bool) -> UInt8 {
    let x = UInt8(UInt(someBool))
    return x
}
Run Code Online (Sandbox Code Playgroud)

编译(“-O”=“优化编译”)

xcrun -sdk macosx swiftc -emit- assembly -O main.swift

给出

    .globl __TF4main3fooFSbVSs5UInt8
    .对齐4,0x90
__TF4main3fooFSbVSs5UInt8:
    .cfi_startproc
    推q%rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    调用 __TFE10FoundationSb19_bridgeToObjectiveCfSbFT_CSo8NSNumber
    movq %rax, %rdi
    调用 __TFE10FoundationSuCfMSuFCSo8NSNumberSu
    movzbl %al、%ecx
    cmpq %rcx, %rax
    jne LBB0_2
    弹出%rbp
    请求

函数名称可以用以下命令进行分解

$ 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 和 Foundation 类型之间的自动转换并生成了一些代码,例如

let x = UInt8(NSNumber(bool: someBool).unsignedLongValue)
Run Code Online (Sandbox Code Playgroud)

两次函数调用可能效率不高。(如果您仅在没有基础的情况下,它不会编译import Swift。)

现在是另一种假设数据相关分支的方法:

func bar(someBool : Bool) -> UInt8 {
    let x = UInt8(someBool ? 1 : 0)
    return x
}
Run Code Online (Sandbox Code Playgroud)

汇编代码是

    .globl __TF4main3barFSbVSs5UInt8
    .对齐4,0x90
__TF4main3barFSbVSs5UInt8:
    推q%rbp
    movq %rsp, %rbp
    andb $1, %dil
    movb %dil, %al
    弹出%rbp
    请求

没有分支,只是一个“AND”运算0x01

因此,我认为没有理由不使用这种“直接”转换。然后,您可以使用 Instruments 进行分析,以检查它是否是您的应用程序的瓶颈。