var num: Int = 25
num = 0b00011001
num = 0o31
num = 0x19
num = 1_000_000
num = 10_000_000
num = 10000_0000
MemoryLayout<Int8>.size // 1바이트
Int8.max // 127 ( 2^7승 -1)
Int8.min // -128 (-2^7승)
MemoryLayout<UInt8>.size // 1바이트
UInt8.max // 255 ( 2^8승 -1)
UInt8.min // 0
MemoryLayout<Int>.size // 8바이트
Int.max // 9223372036854775807 ( 2^63승 -1)
Int.min // -9223372036854775808 (-2^63승 )
UInt8.max // UInt8(8비트의 값을 담을 수 있음)의 최대값 255
UInt8.min // UInt8(8비트의 값을 담을 수 있음)의 최소값 0
//let num: UInt8 = 300
var a = UInt8.max // 현재 변수 a에 UInt8타입의 최대값이 들어있음(255)
a = a &+ 1 // 오버플로우 더하기 연산자로 1을 더하기 ==========> 최소값(0)으로 이동
//a = 0b11111111 &+ 0b00000001
var b = UInt8.min // 현재 변수 b에 UInt8타입의 최소값이 들어있음(0)
b = b &- 1 // 오버플로우 빼기 연산자로 1을 빼기 ==========> 최대값(255)으로 이동
//b = 0b00000000 &- 0b00000001
var a1 = Int8.max // 현재 변수 a1에 Int8타입의 최대값이 들어있음(127)
a1 = a1 &+ 1 // 오버플로우 더하기 연산자로 1을 더하기 ==========> 최소값(-128)으로 이동
//a1 = 0b01111111 &+ 0b00000001
var b1 = Int8.min // 현재 변수 b1에 Int8타입의 최소값이 들어있음(-128)
b1 = b1 &- 1 // 오버플로우 빼기 연산자로 1을 빼기 ==========> 최대값(127)으로 이동
//b1 = -0b10000000 &- 0b00000001
var c1 = Int8.max // 현재 변수 c에 Int8타입의 최대값이 들어있음(127)
c1 = c1 &* 2 // 오버플로우 곱하기 연산자로 2 곱하기 ==========> 비트 한칸씩 이동
//c = 0b01111111 &* 2
!true
!false
true && true
true && false
false && true
false && false
true || true
true || false
false || true
false || false
var num = 0
func checking() -> Bool {
print(#function)
num += 1
return true
}
// if문의 조건식에서 함수를 호출하는 경우
if checking() || checking() { // &&으로 바꿔보기
// &&
}
num
var doorCheck = 0
var passwordCheck = 0
func doorCodeChecking() -> Bool {
doorCheck += 1
print(#function)
return true
}
func passwordCodeChecking() -> Bool {
passwordCheck += 1
print(#function)
return true
}
// 아래 3개의 케이스에서 returnTrue 메서드는 각각 몇 번씩 호출될까?
print("\n[ 첫번째 케이스 ] =============")
if doorCodeChecking() && passwordCodeChecking() && false || true && doorCodeChecking() && passwordCodeChecking() {
}
print("Door: \(doorCheck), Password: \(passwordCheck)")
print("\n[ 두번째 케이스 ] =============")
doorCheck = 0
passwordCheck = 0
if doorCodeChecking() && false && passwordCodeChecking() || doorCodeChecking() || passwordCodeChecking() {
}
print("Door: \(doorCheck), Password: \(passwordCheck)")
print("\n[ 세번째 케이스 ] =============")
doorCheck = 0
passwordCheck = 0
if doorCodeChecking() || passwordCodeChecking() && doorCodeChecking() || false && passwordCodeChecking() {
}
print("Door: \(doorCheck), Password: \(passwordCheck)")
print("\n[ 세번째 케이스를 수정한다면 ] =============")
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)")
===> 논리적인 오류가 없도록 표현식을 미리 실행하도록 코드 수정
(비트 이동 연산자)
5. << : Bitwise Left Shift Operator(비트와이즈 레프트 시프트 연산자)
6. >> : Bitwise Right Shift Operator(비트와이즈 라이트 시프트 연산자)
let a1: UInt8 = 0b0000_1111 // 15
let b1 = ~a1 // 0b1111_0000 // 240
let a2: UInt8 = 0b1111_1100 // 252
let b2: UInt8 = 0b0011_1111 // 63
let c2 = a2 & b2 // 0b0011_1100 // 60
let a3: UInt8 = 0b1011_0010 // 178
let b3: UInt8 = 0b0101_1110 // 94
let c3 = a3 | b3 // 0b1111_1110 // 254
let a4: UInt8 = 0b0001_0100 // 20
let b4: UInt8 = 0b0000_0101 // 5
let c4 = a4 ^ b4 // 0b0001_0001 // 17
(비트 이동 연산자의 기본 원리)
(예) 정수 비트를 왼쪽으로 1칸 이동하면 값이 2배가 됨
(부호가 없는 비트 이동 연산자의 경우) - Unsigned
let leftShiftBits: UInt8 = 4 // 0b0000_0100 // 4
leftShiftBits << 1 // 0b0000_1000 // 8 (곱하기 2)
leftShiftBits << 2 // 0b0001_0000 // 16 (곱하기 2^2승 => 곱하기 4)
leftShiftBits << 5 // 0b1000_0000 // 128 (곱하기 2^5승 => 곱하기 32)
let rightShiftBits: UInt8 = 32 // 0b0010_0000 // 32
rightShiftBits >> 1 // 0b0001_0000 // 16 (나누기 2)
rightShiftBits >> 2 // 0b0000_1000 // 8 (나누기 4)
rightShiftBits >> 5 // 0b0000_0001 // 1 (나누기 2^5승)
(부호가 있는 비트 이동 연산자의 경우) - Signed
let shiftBits: Int8 = 4 // 0b0000_0100 // 4
shiftBits << 1 // 0b0000_1000 // 8 (곱하기 2)
shiftBits << 2 // 0b0001_0000 // 16 (곱하기 4)
shiftBits << 5 // 0b1000_0000 //-128 (곱하기 2^5승, 다만 여기선 범위초과로 오버플로우)
let shiftSignedBits: Int8 = -2 // 0b1111_1110 // -2
shiftSignedBits >> 1 // 0b1111_1111 // -1 (나누기 2) 몫
shiftSignedBits >> 2 // 0b1111_1111 // -1 (나누기 4) 몫
shiftSignedBits >> 5 // 0b1111_1111 // -1 (나누기 2^5승) 몫
(연산자도 사실은 내부적으로 다 구현이 되어있는 타입 메서드임)
"Hello" + ", Swift!" // "Hello, Swift!"
var a = ""
a += "!"
static func + (lhs: String, rhs: String) -> String
static func += (lhs: inout String, rhs: String)
//String.+(lhs: "Hello", rhs: ", Swift!")
// 스위프트 공식 문서의 예제
struct Vector2D {
var x = 0.0
var y = 0.0
}
// 1) 산술 더하기 연산자의 구현 (infix 연산자)
//infix operator + : AdditionPrecedence // 연산자 선언
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
//print(combinedVector)
// 2) 단항 prefix 연산자의 구현 (전치연산자)
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
//print(negative)
let alsoPositive = -negative
//print(alsoPositive)
// 3) 복합할당 연산자의 구현
extension Vector2D {
static func += (left: inout Vector2D, right: Vector2D) {
left = left + right
}
}
"swift" == "Swift" // false
"swift" == "swift" // true
"swift" != "swift" // false
"swift" < "Swift" // false
"swift" >= "Swift" // true
- String 구조체 내부에 타입 메서드로 정의되어 있음
[Equatable 동일성비교에 관한 프로토콜]
static func == (lhs: String, rhs: String) -> Bool
static func != (lhs: String, rhs: String) -> Bool
[Comparable 크기, 순서비교에 관한 프로토콜]
static func < (lhs: String, rhs: String) -> Bool
static func > (lhs: String, rhs: String) -> Bool
static func <= (lhs: String, rhs: String) -> Bool
static func >= (lhs: String, rhs: String) -> Bool
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)
}
// static func !=(lhs: Vector2D, rhs: Vector2D) -> Bool {
// return (lhs.x != rhs.x) || (lhs.y != rhs.y)
// }
}
vector1 == vector2
vector1 != vector2
let twoThree = Vector2D(x: 2.0, y: 3.0)
let anotherTwoThree = Vector2D(x: 2.0, y: 3.0)
if twoThree == anotherTwoThree {
print("두 개의 벡터값은 동일함.")
}
struct Vector2D {
var x = 0.0, y = 0.0
}
extension Vector2D {
static func + (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}
}
extension Vector2D {
static func += (left: inout Vector2D, right: Vector2D) {
left = left + right
}
}
precedencegroup MyPrecedence {
higherThan: AdditionPrecedence
lowerThan: MultiplicationPrecedence
associativity: left // 결합성 ===> left / right / none
}
infix operator +-: MyPrecedence
해당 연산자를 구현하려는 타입에서 타입메서드로 연산자 내용을 직접 구현
extension Vector2D {
static func +- (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y - right.y)
}
}
let firstVector = Vector2D(x: 1.0, y: 2.0)
let secondVector = Vector2D(x: 3.0, y: 4.0)
let plusMinusVector = firstVector +- secondVector
print(plusMinusVector) // Vector2D(x: 4.0, y: -2.0)
우선순위와 결합성의 선언
https://developer.apple.com/documentation/swift/swift_standard_library/operator_declarations
prefix operator +++
extension Vector2D {
static prefix func +++ (vector: inout Vector2D) -> Vector2D {
vector += vector // 복합할당 연산자는 이미 구현되어있기 때문에 사용 가능
return vector
}
}
커스텀 연산자의 사용
var toBeDoubled = Vector2D(x: 1.0, y: 4.0)
let afterDoubling = +++toBeDoubled
// toBeDoubled 의 값은 이제 (2.0, 8.0) 입니다.
// afterDoubling 도 값이 (2.0, 8.0) 입니다.
prefix operator ++
extension Int {
static prefix func ++(number: inout Int) {
number += 1
}
}
var a = 0
++a // +1
++a // +1
++a // +1
print(a)