【问题标题】:conditional operator warning条件运算符警告
【发布时间】:2015-01-05 15:44:23
【问题描述】:

我收到警告,will never be executed 使用以下代码

代码:

func f1()
{
    var a1 : Int = 100

    a1 = 1

    var a2 = (a1 > 40 ? 1 : 0) //No warning

    var a3 = (a1 > 40 ? "aaa" : "bbb") //Warning - will never be executed (points to "aaa")
}

问题:

  • 我知道根据上面的逻辑,a3 会得到"bbb" 的值但是应该有一个 警告?
  • 为什么评估a2的值没有警告
  • 编译器如何实际评估这个?我认为这些值将在运行时确定。 (注意a1的值在赋值后改变了)

【问题讨论】:

  • 我在操场上没有收到任何警告。
  • 我创建了一个 OS X > 命令行工具项目,我收到了警告
  • 我也没有在命令行工具中收到警告。你使用的是什么版本的 Xcode,这是 main.swift 文件中唯一的代码吗?
  • 如果它清除了您的想法,请接受答案。 :)

标签: swift conditional-operator


【解决方案1】:
var a3 = (a1 > 40 ? "aaa" : "bbb") //Warning

之所以会出现warning就行了,是因为它实际上调用了一些代码。它通过调用 String 的 init() 构造一个 String 实例。

a1 > 40 ? 1 : 0

这没有任何警告,因为它是原始值,不涉及任何 init() 或实例创建等。

事情变得有趣了..

    func f1()
    {
        struct F {
            init(x: Int){
            }
        }

        var a1 : Int = 100

        a1 = 1

        var a2 = (a1 > 40 ? Int(1) : Int(0))      // No Warning

        var a4 = (a1 > 40 ? Int(Int(1) + UInt8(2)) : Int(0)) // Warning

        var a3 = (a1 > 40 ? String("aaa") : "bbb")  // Warning

        var a5: F = (a1 > 40 ? F(x: a2) : F(x: a1))  // Warning
    }

为什么a3和a5会收到警告,可以解释一下。但是为什么a2没有警告,它是在调用Int(1),它应该调用struct Int的init()。原因是“编译器优化”。 a4 有警告,说明 swift 编译器的优化比较浅。 :)

编辑

从生成的代码中,您可以看到不同之处。对于简单的 Int(0),不调用结构的 init。

   var a = Int(0)

   0x1006946d0:  pushq  %rbp
   0x1006946d1:  movq   %rsp, %rbp
   0x1006946d4:  subq   $0x20, %rsp
   0x1006946d8:  movq   %rdi, -0x10(%rbp)
   0x1006946dc:  movq   %rdi, -0x18(%rbp)
-> 0x1006946e0:  movq   $0x0, -0x8(%rbp)
   0x1006946e8:  callq  0x1006b0f14               ; symbol stub for: objc_release
   0x1006946ed:  addq   $0x20, %rsp
   0x1006946f1:  popq   %rbp
   0x1006946f2:  retq   

   var a2 = Int(Int(0x0) + UInt8(0xE))

   0x1007175f0:  addq   $0x8, %rax
   0x1007175f6:  movq   0x1ebc3(%rip), %r8        ; (void *)0x0000000104a89d88: protocol witness table for Swift.UInt8 : Swift.Strideable
   0x1007175fd:  movq   0x1eaac(%rip), %rcx       ; (void *)0x0000000104a92f80: direct type metadata for Swift.Int
   0x100717604:  addq   $0x8, %rcx
   0x10071760b:  movq   0x1eb5e(%rip), %rdx       ; (void *)0x0000000104a8b228: protocol witness table for Swift.Int : Swift.SignedNumberType
   0x100717612:  movq   0x1eb67(%rip), %rsi       ; (void *)0x0000000104a8b0c8: protocol witness table for Swift.Int : Swift._BuiltinIntegerLiteralConvertible
   0x100717619:  leaq   -0x38(%rbp), %r9
   0x10071761d:  leaq   -0x30(%rbp), %r10
   0x100717621:  leaq   -0x28(%rbp), %r11
   0x100717625:  movq   %rdi, -0x18(%rbp)
   0x100717629:  movq   %rdi, -0x20(%rbp)
-> 0x10071762d:  movq   $0xb, -0x28(%rbp)
   0x100717635:  movb   $0xe, -0x30(%rbp)
   0x100717639:  movq   %rdi, -0x40(%rbp)
   0x10071763d:  movq   %r9, %rdi
   0x100717640:  movq   %rsi, -0x48(%rbp)
   0x100717644:  movq   %r11, %rsi
   0x100717647:  movq   %rdx, -0x50(%rbp)

【讨论】:

  • Int 和 String 在 Swift 中都是结构体。试试下面的代码:var a2 = (a1 > 40 ? Int(1) : Int(0)) //No warning 所以两者都调用了初始化程序/构造函数,但没有对 Int 的警告,而对 String 有警告
  • a2 和 a3 相似,但 a2 没有警告,a3 有警告。两者都使用构造函数/初始化程序。而且 a4 有一个警告……让它更有趣(令人困惑)
  • @user1046037 这就是编译器优化的用武之地。Swift 编译器试图生成高性能代码,因此它删除了 Int() 的 init。有兴趣可以阅读生成的程序集。
  • @user1046037 打开一个新问题?
猜你喜欢
  • 2016-05-06
  • 2016-07-13
  • 2016-11-08
  • 2023-03-20
  • 2017-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-05
相关资源
最近更新 更多