🔥 오버플로우 연산자

469자
7분

강의 목차

Swift는 안전한 프로그래밍을 위해 정수형 상수나 변수에 값을 할당할 때, 해당 타입이 저장할 수 있는 범위를 벗어나는 값을 할당하려고 하면 에러를 발생시켜요. 이러한 동작은 너무 크거나 작은 숫자를 다룰 때 추가적인 안전성을 제공하죠.

예를 들어, Int16 정수 타입은 -32768에서 32767 사이의 어떤 부호 있는 정수도 저장할 수 있어요. 이 범위를 벗어난 숫자를 Int16 상수나 변수에 설정하려고 하면 에러가 발생한답니다.

var potentialOverflow = Int16.max
// potentialOverflow는 Int16이 저장할 수 있는 최댓값인 32767과 같아요.
potentialOverflow += 1
// 이는 에러를 발생시킨답니다.
swift

값이 너무 크거나 작아질 때 에러 처리를 제공하면 경계값 조건에 대한 코딩을 할 때 훨씬 더 유연성을 발휘할 수 있게 되죠.

하지만 오버플로 조건이 발생했을 때 사용 가능한 비트 수를 잘라내려는 경우에는 에러를 트리거하는 대신 이러한 동작을 선택할 수 있어요. Swift는 정수 계산에 대해 오버플로 동작을 선택할 수 있는 세 가지 산술 오버플로우 연산자를 제공하고 있죠. 이 연산자들은 모두 앰퍼샌드(&)로 시작한답니다:

  • 오버플로우 덧셈 (&+)
  • 오버플로우 뺄셈 (&-)
  • 오버플로우 곱셈 (&*)

값 오버플로우

숫자는 양수 방향과 음수 방향 모두로 오버플로될 수 있어요.

다음은 오버플로 덧셈 연산자(&+)를 사용하여 부호 없는 정수가 양수 방향으로 오버플로되는 경우에 대한 예시랍니다:

var unsignedOverflow = UInt8.max
// unsignedOverflow는 UInt8이 저장할 수 있는 최댓값인 255와 같네요.
unsignedOverflow = unsignedOverflow &+ 1
// unsignedOverflow는 이제 0과 같아졌어요.
swift

unsignedOverflow 변수는 UInt8이 저장할 수 있는 최댓값(255 또는 이진수로 11111111)으로 초기화됩니다. 그런 다음 오버플로 덧셈 연산자(&+)를 사용하여 1을 증가시키죠. 이는 이진 표현을 UInt8이 저장할 수 있는 크기를 살짝 넘어서게 밀어내어, 아래 다이어그램에서 볼 수 있듯이 해당 범위를 벗어나 오버플로되게 만들어요. 오버플로 덧셈 후 UInt8의 범위 내에 남아 있는 값은 00000000 즉, 0이랍니다.

lecture image

부호 없는 정수가 음수 방향으로 오버플로되는 경우에도 비슷한 일이 일어나요. 다음은 오버플로 뺄셈 연산자(&-)를 사용한 예시입니다:

var unsignedOverflow = UInt8.min
// unsignedOverflow는 UInt8이 저장할 수 있는 최솟값인 0과 같네요.
unsignedOverflow = unsignedOverflow &- 1
// unsignedOverflow는 이제 255와 같아졌어요.
swift

UInt8이 저장할 수 있는 최솟값은 0 또는 이진수로 00000000이에요. 오버플로 뺄셈 연산자(&-)를 사용하여 00000000에서 1을 빼면, 숫자가 오버플로되어 11111111 즉, 10진수로 255로 넘어가게 된답니다.

lecture image

부호 있는 정수에서도 오버플로가 발생해요. Bitwise Left and Right Shift Operators 에서 설명한 대로, 부호 있는 정수에 대한 모든 덧셈과 뺄셈은 부호 비트를 더하거나 빼는 숫자의 일부로 포함하여 비트 단위로 수행된답니다.

var signedOverflow = Int8.min
// signedOverflow는 Int8이 저장할 수 있는 최솟값인 -128과 같네요.
signedOverflow = signedOverflow &- 1
// signedOverflow는 이제 127과 같아졌어요.
swift

Int8이 저장할 수 있는 최솟값은 -128 또는 이진수로 10000000이에요. 오버플로 연산자를 사용하여 이 이진수에서 1을 빼면 01111111이라는 이진값이 되는데, 이는 부호 비트를 토글하고 Int8이 저장할 수 있는 최댓값인 양수 127을 제공하죠.

lecture image

부호 있는 정수와 부호 없는 정수 모두에서, 양수 방향으로의 오버플로는 최댓값에서 최솟값으로 다시 넘어가고, 음수 방향으로의 오버플로는 최솟값에서 최댓값으로 넘어간답니다.

이처럼 Swift의 오버플로우 연산자는 정수 계산 시 오버플로 동작을 선택할 수 있게 해주어, 경계값 조건에 대한 유연한 프로그래밍을 가능하게 해줘요. 하지만 오버플로를 적절히 처리하지 않으면 예기치 않은 결과를 초래할 수 있으므로, 사용 시 주의가 필요하답니다.