C Pointers

C Pointers

포인터를 처음 접할 때 많이 하는 실수 중 하나가 "C 포인터를 어디에나 써야지" 하는 생각이에요. 그런데 이 타입은 되도록 피하는 게 좋아요. 쓰기에 정당한 이유가 있는 유일한 곳은, C 코드를 번역해서 자동 생성된 코드 안이에요.

출처: Zig Documentation

본문

C 헤더 파일을 임포트할 때 보면, 포인터를 단일 항목 포인터(*T)로 번역해야 할지, 다중 항목 포인터([*]T)로 번역해야 할지 애매한 경우가 있어요. C 포인터는 이런 애매함을 타협해서 만든 타입이에요. 덕분에 Zig 코드가 번역된 헤더 파일을 그대로 활용할 수 있죠.

[*c]T

위 코드가 C 포인터를 나타내는 문법이에요. C 포인터는 이렇게 동작해요.

  • 다른 두 포인터 타입(*T)과 ([*]T)의 문법을 모두 지원해요.
  • 다른 포인터 타입은 물론 Optional Pointers로도 강제 변환(coerce)돼요. 그런데 C 포인터를 non-optional 포인터로 변환할 때, 주소가 0이면 안전 검사로 잡히는 Illegal Behavior가 발생해요.
  • 주소 0을 허용해요. 다만 freestanding이 아닌 타깃에서는 주소 0을 역참조(dereference)하는 게 안전 검사로 잡히는 Illegal Behavior예요. Optional C 포인터는 ?usize처럼 null을 추적하기 위한 비트를 하나 더 가지게 돼요. 다만 어차피 일반 Optional Pointers를 쓰면 되니까, Optional C 포인터를 만들 필요는 없어요.
  • 정수와 Type Coercion을 주고받을 수 있어요.
  • 정수와 비교할 수 있어요.
  • 정렬(alignment) 같은 Zig 전용 포인터 속성은 지원하지 않아요. 그런 게 필요하면 일반 Pointers를 써주세요!

C 포인터가 배열이 아닌 단일 구조체를 가리킬 때는, 구조체의 필드나 멤버 데이터에 접근하기 위해 C 포인터를 역참조해야 해요. 문법은 이렇게 생겼어요.

ptr_to_struct.*.struct_member

이건 C에서 ->를 쓰는 것과 비슷한 느낌이에요. 반면 C 포인터가 구조체의 배열을 가리키는 경우에는 문법이 이렇게 돌아와요.

ptr_to_struct_array[index].struct_member

더 알아보기

  • Pointers — Zig에서 주로 쓰는 일반 포인터 타입이에요.
  • Optional Pointers — null일 수 있는 포인터를 다루는 방법이에요.
  • Type Coercion — 포인터 타입들이 서로 변환되는 규칙이에요.
  • Illegal Behavior — 주소 0 관련 안전 검사가 무엇인지 알아볼 수 있어요.