정수
정수 (Integers)
Zig에서 정수를 다루는 기본기를 하나씩 짚어볼게요. 정수 리터럴을 어떤 진법으로 쓸 수 있는지, 그리고 컴파일 타임과 런타임에서 정수 값이 어떻게 취급되는지를 중심으로 살펴봐요. 코드부터 직접 보면서 익히는 게 훨씬 와닿을 거예요.
본문
정수 리터럴 (Integer Literals)
정수 리터럴은 십진수만 쓰는 게 아니라 여러 진법으로 표현할 수 있어요. 아래 코드를 한번 볼게요.
const decimal_int = 98222;
const hex_int = 0xff;
const another_hex_int = 0xFF;
const octal_int = 0o755;
const binary_int = 0b11110000;
// underscores may be placed between two digits as a visual separator
const one_billion = 1_000_000_000;
const binary_mask = 0b1_1111_1111;
const permissions = 0o7_5_5;
const big_address = 0xFF80_0000_0000_0000;
0x는 16진수, 0o는 8진수, 0b는 2진수를 나타내요. 그리고 자릿수 사이에 밑줄(_)을 넣어서 가독성을 높일 수도 있어요. 예를 들어 1_000_000_000이 1000000000보다 훨씬 읽기 편하지요. 밑줄은 숫자 두 개 사이에만 놓을 수 있다는 점만 기억해 두면 돼요.
런타임 정수 값 (Runtime Integer Values)
정수 리터럴은 크기 제한이 없어요. 그래서 정수 리터럴을 쓰는 동안 어떤 문제(Illegal Behavior)가 생기면, 컴파일러가 그 자리에서 잡아내 줘요.
하지만 정수 값이 컴파일 타임에 더 이상 알려지지 않고 런타임에만 알려지게 되면, 얘기가 달라져요. 반드시 크기가 정해져 있어야 하고, 안전 검사가 적용되는 문제(Illegal Behavior)에 취약해지거든요. 아래 함수를 볼게요.
fn divide(a: i32, b: i32) i32 {
return a / b;
}
이 함수에서 a와 b 값은 런타임에만 알려져요. 그래서 이 나눗셈 연산은 정수 오버플로(Integer Overflow)와 0으로 나누기(Division by Zero) 양쪽 모두에 노출될 수밖에 없죠.
+나 - 같은 연산자는 정수 오버플로가 나면 문제(Illegal Behavior)를 일으켜요. 이런 상황을 위해 모든 대상(target)에서 동작하는 wrapping(감싸기)과 saturating(포화) 산술용 대체 연산자가 따로 마련돼 있어요. +%와 -%는 wrapping 산술을, +|와 -|는 saturating 산술을 수행해요.
Zig는 임의의 비트 폭을 가진 정수를 지원해요. i 또는 u 뒤에 숫자가 붙는 식별자로 참조하지요. 예를 들어 i7은 부호 있는 7비트 정수를 뜻해요. 정수 타입의 최대 허용 비트 폭은 65535예요. 그리고 부호 있는 정수 타입의 경우 Zig는 2의 보수(two's complement) 표현을 사용해요.
더 알아보기 (Learn more)
- Wrapping Operations — wrapping 산술 연산에 대해 더 자세히 보고 싶다면 이어서 살펴보세요.