Zig 란?
숨겨진 제어
숨겨진 메모리 할당
숨겨진 전처리기
숨겨진 매크로
이 모든 숨겨진 것들을 없앤 프로그래밍 언어!
필요성
작고 간단하다.
var a = b + c.d;
foo();
bar();
# C++,D,Rust 에는 "오버로딩"이 존재, + 연산자가 함수 호출 가능 // Zig 는 불가능
# C++,D,Go 에는 throw/catch가 존재, foo()에서 예외처리(throw)를 하고, bar() 호출 방지 // Zig는 호출
Zig에서, "보이는게 전부이다."
Zig는 모든 제어 흐름이 "언어 키워드, 함수 호출" 로만 관리된다
- 가독성 좋음(이해하기 쉬움), 유지보수 좋음
그럼 에러는 어떻게 관리함??
여러 빌드 모드 사용
에러를 어디까지 볼것인지, 선택가능!
- Zig는 모든 에러를, 컴파일 타임에 잡아낼 수 있다.
실행코드 ( 정수형 변수 오버플로우 에러 예제 )
test "integer overflow at compile time" {
const x: u8 = 255;
_ = x + 1;
}
일반 모드 에러
zig test test.zig
doctest-20bd10f2/test.zig:3:11: error: overflow of integer type 'u8' with value '256'
_ = x + 1;
~~^~~
안전 모드 에러
zig test test.zig
1/1 test.integer overflow at runtime... thread 2593 panic: integer overflow
/home/runner/work/www.ziglang.org/www.ziglang.org/doctest-3b4a2e36/test.zig:3:7: 0x20dce4 in test.integer overflow at runtime (test)
x += 1;
^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/test_runner.zig:178:28: 0x217176 in mainTerminal (test)
} else test_fn.func();
^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/test_runner.zig:38:28: 0x20f2c7 in main (test)
return mainTerminal();
^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:607:22: 0x20e5b5 in posixCallMainAndExit (test)
root.main();
^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:376:5: 0x20e061 in _start (test)
@call(.never_inline, posixCallMainAndExit, .{});
^
error: the following test command crashed:
/home/runner/.cache/zig/o/92d9094ece372827fed22988becdced3/test
자세한 실행 순서 ( 호출 스택 )을 확인할 수 있어서, 버그를 고치기 쉽다 ( 디버깅 )
모든 플랫폼에서, 동일한 개발환경 구축
# intel
zig cc -o hello hello.c -target x86_64-windows
# apple arm
zig cc -o hello hello.c -target aarch64-macos
# c++
zig c++ hello hello.cpp
# arm gnu
zig cc -o hello hello.c -target aarch64-linux-gnu.2.31
# arm musl
zig cc -o hello hello.c -target aarch64-linux-musl
C언어 기반의 모든언어를 컴파일 할 수 있다!
C언어 + Zig
// test.zig
const std = @import("std");
pub fn build(b: *std.build.Builder) void {
const target = b.standardTargetOptions(.{});
const mode = b.standardReleaseOptions();
// zig파일 불러서, 실행가능한 형식으로 넣기
const exe = b.addExecutable("foobar", "arc/foo.zig");
// c파일 불러서, 위에서 만든 코드와 합치기
exe.addSourceFile("src/bar.c", &.{"-std=c99"});
exe.setTarget(target);
exe.setBuildMode(mode);
exe.linkLibC();
exe.install();
}
Zig
// foo.zig
const std = @import("std");
// 호출 스택 삭제 함수
export fn dump_stack_trace() void {
std.debug.dumpCurrentStackTrace(null);
}
// i32(32bit integer) 형식의 데이터를 가리키는 주소와, 배열의 전체 길이를 받아서
// i32 형식의 값을 반환하는 함수
export fn sum_array(ints_ptr: [*]const i32, ints_len: usize) i32 {
// 배열의 길이 만큼, 원소하나하나 더하기
return sumArray(ints_ptr[0..ints_len]);
}
// ints: []const i32 (i32타입으로 채워진 배열)을 받아서
// i32 형식의 값을 반환하는 함수
fn sumArray(ints: []const i32) i32 {
var sum: i32 = 0; // 합계 저장할 변수 선언
for (ints) |int| { // ints 길이만큼 반복해서, int에 배열원소 대입
sum += int;
}
return sum;
}
pub const _start = void;
C
#include <stdio.h>
// zig 파일의 함수 원형 선언 (zig to c!!)
void dump_stack_trace(void);
int sum_array(int *ptr, size_t len); // 인자 타입 맞춰주기
static void foo(int dump) {
if (dump) {
dump_stack_trace(); // use zig ㄷㄷ
}
}
int main(int argc, char **argv) {
int array[5] = {1, 0, 4, 5, 10};
int result = sum_array(array, 5); // zig
printf("result: %d\n", result);
foo(argc > 1);
return 0;
}
------ 작성중
컴파일 타임에 모든 함수 호출
런타임 오버헤드 없이 type as value 조절
반응형