liminfo

Zig Reference

Zig 프로그래밍 레퍼런스

29개 결과

Zig Reference 소개

Zig 레퍼런스는 명시적 메모리 관리, 컴파일 타임 평가, 제로 숨겨진 제어 흐름에 초점을 맞춘 C 및 C++의 실용적 대안으로 설계된 시스템 프로그래밍 언어인 Zig에 대한 종합적이고 검색 가능한 가이드입니다. const/var 선언, if/else 표현식(문이 아님), 캡처 구문이 있는 while/for 루프, 범위 패턴이 있는 switch 표현식, 함수 정의, 메서드가 있는 구조체, 열거형, 태그드 유니온을 포함한 Zig의 핵심 구문을 다룹니다.

이 레퍼런스는 Zig의 기능을 여섯 가지 핵심 카테고리로 분류합니다. 기본 문법(선언, 제어 흐름, 함수, 구조체, 열거형, 유니온), 타입(u8부터 u64/usize까지의 정수 타입, 실수, if-unwrap을 통한 페이로드 캡처가 있는 옵셔널 ?T, 슬라이스 []T, 포인터 *T), 메모리(할당자 인터페이스, ArrayList, 결정적 정리를 위한 defer/errdefer, @memcpy/@memset 내장 함수), 에러 처리(에러 유니온 !T, 전파를 위한 try, 복구를 위한 catch, 명명된 에러 집합), 컴파일 타임(컴파일 타임 실행 블록, 제네릭 프로그래밍을 위한 comptime 매개변수, @typeInfo 리플렉션, inline for 루프 풀기), 테스트(테스트 블록, expect/expectEqual 단언, 테스트 필터링, 누수 감지를 위한 std.testing.allocator)입니다.

Zig는 매크로, 템플릿, 제네릭을 하나의 통합된 메커니즘으로 대체하는 comptime 시스템으로 다른 시스템 언어와 차별화됩니다. 함수가 comptime 매개변수를 받아 컴파일 타임에 특화된 타입을 생성하고, @typeInfo가 리플렉션 기반 제네릭 프로그래밍을 가능하게 하며, inline for가 각 구조체 필드에 대해 컴파일 타임에 루프를 풀어냅니다. 명시적 할당자 전달(숨겨진 할당 없음), 타입 시스템에서 에러 처리를 가시화하는 에러 유니온, 결정적 리소스 정리를 위한 defer/errdefer와 결합하여 Zig는 C의 저수준 제어력에 현대적 안전 기능을 제공합니다.

주요 기능

  • u8/i8부터 u64/i64까지의 완전한 정수 타입 시스템과 usize, 16진수(0xFF), 8진수(0o77), 시각적 구분자 지원
  • null 안전 값 추출을 위한 if-unwrap 페이로드 캡처 구문이 있는 옵셔널 타입(?T)
  • 명명된 에러 집합, try 전파, 기본값 catch를 갖춘 에러 유니온(!T) 시스템
  • 컴파일 타임 함수 매개변수, @typeInfo 리플렉션, inline for 풀기를 활용한 comptime 메타프로그래밍
  • page_allocator, ArrayList, defer/errdefer 정리 패턴을 활용한 할당자 기반 메모리 관리
  • switch 기반 패턴 매칭을 사용하는 타입 안전 변형 타입을 위한 태그드 유니온(union(enum))
  • 테스트 블록, std.testing.expectEqual 단언, std.testing.allocator를 통한 메모리 누수 감지가 포함된 내장 테스트 프레임워크
  • 경계 검사 인덱싱과 ptr.*를 통한 명시적 역참조가 있는 슬라이스([]T)와 포인터(*T) 타입

자주 묻는 질문

Zig의 comptime 시스템은 매크로와 제네릭을 어떻게 대체하나요?

Zig의 comptime 키워드는 동일한 언어를 사용하여 어떤 코드든 컴파일 타임에 실행할 수 있게 하여 별도의 매크로 구문이나 템플릿 메타프로그래밍의 필요성을 제거합니다. 함수가 comptime 매개변수(예: comptime T: type)를 받아 특화된 타입을 생성하여 효과적으로 제네릭을 구현합니다. 예를 들어 fn Matrix(comptime T: type, comptime rows: usize, comptime cols: usize) type은 [rows][cols]T 타입의 data 필드를 가진 구조체를 반환합니다. @typeInfo 내장 함수가 리플렉션을 가능하게 하고, inline for가 컴파일 타임에 구조체 필드에 대한 루프를 풀어냅니다.

Zig에서 defer와 errdefer의 차이점은 무엇인가요?

defer는 함수가 정상적으로 반환하든 에러로 반환하든 관계없이 둘러싸는 스코프를 빠져나갈 때 표현식을 실행합니다. file.close()나 allocator.free() 같은 결정적 리소스 정리에 사용됩니다. errdefer는 함수가 에러를 반환할 때만 실행되어 실패 경로에서만 수행해야 하는 정리에 이상적입니다. 예를 들어, 버퍼 할당 후 errdefer allocator.free(buf)는 후속 작업이 실패하면 버퍼를 해제하지만 성공 시에는 할당 상태를 유지합니다.

에러 유니온과 try/catch는 Zig에서 어떻게 동작하나요?

에러 유니온(ErrorSet!PayloadType)은 성공과 실패를 모두 반환 타입에 인코딩하여 타입 시스템에서 에러 처리를 가시화합니다. try 키워드는 에러를 위로 전파합니다: const data = try readFile("input.txt")는 readFile이 실패하면 호출자에게 에러를 반환합니다. catch 키워드는 에러를 로컬에서 처리합니다: compute() catch 0은 기본값을 제공하고, catch |err| { ... }는 복구 로직을 실행합니다. 명명된 에러 집합(const E = error{NotFound, PermissionDenied})은 도메인별 에러 타입을 정의합니다.

Zig의 옵셔널 타입(?T)은 null 포인터 에러를 어떻게 방지하나요?

옵셔널 타입(?T)은 부재의 가능성을 타입 시스템에 명시적으로 인코딩합니다. ?i32는 i32 값 또는 null을 가질 수 있습니다. 내부 값에 접근하려면 if-unwrap을 사용해야 합니다: if (x) |val| { use(val); }는 x가 null이 아닐 때만 블록에 진입하며, val은 언래핑된 값에 바인딩됩니다. 옵셔널을 먼저 검사하지 않고는 사용할 수 없으므로 컴파일 타임에 null 포인터 역참조를 제거합니다.

Zig가 malloc 대신 명시적 할당자 전달을 요구하는 이유는 무엇인가요?

Zig는 모든 메모리 할당을 가시적이고 제어 가능하게 만들기 위해 할당자를 명시적으로 전달하도록 요구합니다. 숨겨진 전역 할당자나 암시적 힙 할당이 없습니다. 이 설계는 컨텍스트별로 할당자를 교체할 수 있게 합니다: 프로덕션에서는 page_allocator, 테스트에서는 메모리 누수를 감지하는 std.testing.allocator, 배치 할당을 위한 arena 할당자, 스택 기반 할당을 위한 고정 버퍼 할당자를 사용합니다. 모든 할당 지점이 소스에서 명시적으로 보이므로 코드 감사도 용이합니다.

Zig에서 태그드 유니온이란 무엇이며 어떻게 사용하나요?

태그드 유니온(union(enum))은 유니온과 열거형 판별자를 결합하여 타입 안전한 변형 타입을 가능하게 합니다. const Value = union(enum) { int: i32, float: f64, none: void }를 선언하면 한 번에 정확히 하나의 변형만 가질 수 있는 타입이 생성됩니다. 태그드 유니온에 대한 switch 표현식은 전수적(exhaustive)이어서 컴파일러가 모든 변형이 처리되었는지 보장합니다. 이것은 여러 다른 타입 중 하나가 될 수 있는 값을 나타내는 데 사용되는 Zig의 합 타입 접근 방식입니다.

Zig의 내장 테스트 프레임워크는 어떻게 동작하나요?

Zig에는 언어에 내장된 일급 테스트 프레임워크가 있습니다. 테스트 블록은 테스트하는 코드 옆에 test "name" { ... }로 소스 파일에 직접 선언됩니다. 단언은 try std.testing.expectEqual(expected, actual)과 try std.testing.expect(condition)을 사용합니다. zig test src/main.zig로 모든 테스트를 실행하고, --test-filter로 특정 테스트만 실행할 수 있습니다. std.testing.allocator는 모든 할당을 추적하고 해제되지 않은 할당이 있으면 테스트를 실패시켜 메모리 누수를 감지합니다.

Zig에서 슬라이스와 포인터는 어떻게 다른가요?

포인터(*T)는 T 타입의 단일 값을 참조하며 ptr.* 구문으로 역참조합니다. 슬라이스([]T)는 연속된 시퀀스의 시작 포인터와 길이를 모두 포함하는 팻 포인터로, 경계 검사 인덱싱을 가능하게 합니다. 슬라이스는 범위 구문으로 배열에서 생성됩니다: arr[1..4]는 3개 요소의 슬라이스를 생성합니다. const 슬라이스([]const T)는 기본 데이터의 수정을 방지합니다. 슬라이스는 연속된 메모리 영역을 안전하게 다루기 위한 Zig의 주요 추상화입니다.