Languages

[Zig] Zig란? / 사용법

MOONCO 2023. 3. 27. 01:49

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 조절

 

 

 
반응형