숫자 리터럴
var num: Int = 25
num = 0b00011001
num = 0o31
num = 0x19
num = 1_000_000
num = 10_000_000
num = 10000_0000
MemoryLayout<Int8>.size
Int8.max
Int8.min
MemoryLayout<UInt8>.size
UInt8.max
UInt8.min
MemoryLayout<Int>.size
Int.max
Int.min
오버플로우
- C에서는 오버플로우를 허용(숫자가 넘어가면 0으로 돌아감)하지만,
스위프트에서는 오버플로우를 허용하지 않는다
- 특정 경우, 특정 패턴을 구현하기 위해 오버플로우를 허용하는 경우가 필요한데,
이를 위해 오버플로우 연산자를 마련해 두었다.
오버플로우 연산자
- &+ : 오버플로우 더하기
- &- : 오버플로우 빼기
- &* : 오버플로우 곱하기
var a = UInt8.max
a = a &+ 1
var b = UInt8.min
b = b &- 1
var c = Int8.max
c = c &+ 1
var d = Int8.min
d = d &- 1
var e = Int8.max
e = e &* 2
논리 연산자와 단락 평가
!true
true && false
false && true
true || false
단락 평가
- 스위프트의 논리 평가식은 단락 평가 방식을 사용한다
- 단락 평가 : 논리 평가식에서 결과도출에 필요한 최소한의 논리식만 평가한다
var num = 0
func checking() -> Bool {
print(#function)
num += 1
return true
}
if checking() || checking() {
}
단락 평가에서 발생할 수 있는 문제
- side effect 발생 시 반드시 주의해야 한다
- 단락평가로 인해 함수의 실행횟수의 차이로 인해 의도치 않은 결과가 도출될 수 있다
var doorCheck = 0
var passwordCheck = 0
func doorCodeCheckinig() -> Bool {
doorCheck += 1
print(#function)
return true
}
func passwordCodeChecking() -> Bool {
passwordCheck += 1
print(#function)
return true
}
if doorCodeChecking() && passwordCodeChecking() && false || true
&& doorCodeChecking() && passwordCodeChecking() {
}
print(Door: \(doorCheck), Password: \(passwordCheck)")
doorCheck = 0
passwordCheck = 0
if doorCodeChecking() && false && passwordCodeChecking() || doorCodeChecking()
|| passwordCodeChecking() {
}
print(Door: \(doorCheck), Password: \(passwordCheck)")
doorCheck = 0
passwordCheck = 0
if doorCodeChecking() || passwordCodeChecking() && doorCodeChecking()
|| false && passwordCodeChecking() {
}
print(Door: \(doorCheck), Password: \(passwordCheck)")
doorCheck = 0
passwordCheck = 0
let doorResult1 = doorCodeChecking()
let passwordResult1 = passwordCodeChecking()
let doorResult2 = doorCodeChecking()
let passwordResult2 = passwordCodeChecking()
if doorResult1 || passwordResult1 && doorResult1 || false && passwordResult2 {
}
print("Door: \(doorCheck), Password: \(passwordCheck)")
비트 연산자
비트 연산자
let a1: UInt8 = 0b0000_1111
let b1: ~a1
let a2: UInt8 = 0b1111_1100
let b2: UInt8 = 0b0011_1111
let c2 = a2 & b2
let a3: UInt8 = 0b1011_0010
let b3: UInt8 = 0b0101_1110
let c3 = a3 | b3
let a4: UInt8 = 0b0001_0100
let b4: UInt8 = 0b0000_0101
let c4 = a4 ^ b4
- << : Bitwise Left Shift
- >> : Bitwise Right Shift
- Signed일 때, 만약 부호가 있으면(MSB가 1이면) 오른쪽으로 밀고 남은 공간에 1 넣어주기
연산자 메서드의 직접 구현
- 연산자 :
타입.함수이름(파라미터: 타입)
형태로 실행하지 않는 특별한 형태의 타입 메서드
static func + (lhs: String, rhs: String) -> String
static func += (lhs: inout String, rhs: String)
struct Vector2D {
var x = 0.0
var y = 0.0
}
extension Vector2D {
static func + (lhs: Vector2D, rhs: Vector2D) -> Vector2D {
return Vector2D(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
}
}
let vector = Vector2D(x: 3.0, y: 1.0)
let anotherVector = Vector2D(x: 2.0, y: 4.0)
let combinedVector = vector + anotherVector
extension Vector2D {
static prefix func - (vector: Vector2D) -> Vector2D {
return Vector2D(x: -vector.x, y: -vector.y)
}
}
let positive = Vector2D(x: 3.0, y: 4.0)
let negative = -positive
extension Vector2D {
static func += (left: inout Vector2ㅇ, right: Vector2D) {
left = left + right
}
}
let vector1 = Vector2D(x: 1.0, y: 2.0)
let vector2 = Vector2D(x: 2.0, y: 3.0)
vector1 == vector2
extension Vector2D: Equatable {
static func ==(lhs: Vector2D, rhs: Vector2D) -> Bool {
return (lhs.x == rhs.x) && (lhs.y == rhs.y)
}
}
vector1 == vector2