What is the difference between var a = 5 and var a = Int(5)?

  • A+
Category:Languages

Is there any difference literal value and integer literal value when declaring a variable?

 


Before optimization, yes, these are different. var a = 5 is immediately optimized to give future references to a the value of 5. var a = Int(5) includes a function call to SignedInteger.init. You can see this by emitting the SIL:

echo "var x = 5" | swiftc -emit-sil -  // main sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):   alloc_global @$S4main1xSivp                     // id: %2   %3 = global_addr @$S4main1xSivp : $*Int         // user: %6   %4 = integer_literal $Builtin.Int64, 5          // user: %5   %5 = struct $Int (%4 : $Builtin.Int64)          // user: %6   store %5 to %3 : $*Int                          // id: %6   %7 = integer_literal $Builtin.Int32, 0          // user: %8   %8 = struct $Int32 (%7 : $Builtin.Int32)        // user: %9   return %8 : $Int32                              // id: %9 } // end sil function 'main' 

echo "var x = Int(5)" | swiftc -emit-sil -  // main sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):   alloc_global @$S4main1xSivp                     // id: %2   %3 = global_addr @$S4main1xSivp : $*Int         // user: %11   %4 = metatype $@thin Int.Type   %5 = metatype $@thick Int.Type                  // user: %11   %6 = integer_literal $Builtin.Int64, 5          // user: %7   %7 = struct $Int (%6 : $Builtin.Int64)          // user: %9   %8 = alloc_stack $Int                           // users: %9, %12, %11   store %7 to %8 : $*Int                          // id: %9   // function_ref SignedInteger<>.init<A>(_:)   %10 = function_ref @$SSZss17FixedWidthIntegerRzrlEyxqd__cSzRd__lufC : $@convention(method) <τ_0_0 where τ_0_0 : FixedWidthInteger, τ_0_0 : SignedInteger><τ_1_0 where τ_1_0 : BinaryInteger> (@in τ_1_0, @thick τ_0_0.Type) -> @out τ_0_0 // user: %11   %11 = apply %10<Int, Int>(%3, %8, %5) : $@convention(method) <τ_0_0 where τ_0_0 : FixedWidthInteger, τ_0_0 : SignedInteger><τ_1_0 where τ_1_0 : BinaryInteger> (@in τ_1_0, @thick τ_0_0.Type) -> @out τ_0_0   dealloc_stack %8 : $*Int                        // id: %12   %13 = integer_literal $Builtin.Int32, 0         // user: %14   %14 = struct $Int32 (%13 : $Builtin.Int32)      // user: %15   return %14 : $Int32                             // id: %15 } // end sil function 'main' 

However, once it's optimized (add -O to the swiftc lines), they're (basically) identical to the var a = 5 version:

// main sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):   alloc_global @$S4main1xSivp                     // id: %2   %3 = global_addr @$S4main1xSivp : $*Int         // user: %6   %4 = integer_literal $Builtin.Int64, 5          // user: %5   %5 = struct $Int (%4 : $Builtin.Int64)          // user: %6   store %5 to %3 : $*Int                          // id: %6   %7 = integer_literal $Builtin.Int32, 0          // user: %8   %8 = struct $Int32 (%7 : $Builtin.Int32)        // user: %9   return %8 : $Int32                              // id: %9 } // end sil function 'main' 

The latter will emit a huge amount of additional SIL for protocol witnesses that aren't actually used, but this won't impact the final binary.

You can explore the final assembly output with godbolt:

As you'll note, the optimized versions are exactly identical.

In practice, it really doesn't matter. It is common style in Swift to omit the type, but there are many cases where it's needed, such as for UInt or Int64 types, and even Int() can be useful for clarity sometimes.

Whether you write it var a: UInt = 5 or var a = UInt(5) is just style, even though they lead to slightly different unoptimized output. Rest assured that the optimizer will easily fix up any of these approaches for you, and just write in the style that is most clear to your problem. But when in doubt, leave it out. That's the typical preference in Swift.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: