12P by GN⁺ 1일전 | ★ favorite | 댓글 3개
  • C 언어의 문법과 의미를 계승하면서 안전성과 사용성을 강화한 진화형 언어로, 기존 C 개발자에게 익숙한 환경을 유지
  • 완전한 C ABI 호환성을 제공해 C/C++ 프로젝트에 바로 통합 가능하며, vkQuake 일부 코드가 C3로 변환되어 c3c 컴파일러로 빌드된 사례 존재
  • 모듈 시스템, 연산자 오버로딩, 컴파일 타임 매크로 등으로 코드 구조와 표현력을 향상
  • 계약 기반 프로그래밍(Gradual Contracts) , 제로 오버헤드 오류 처리, 런타임 및 컴파일 타임 리플렉션 등 현대적 기능을 포함
  • 디버그 모드에서 안전 검사와 상세 스택트레이스를 자동 제공해 버그 탐지와 안정성 확보에 유리

C3 개요

  • C3는 C 언어의 문법(syntax)의미(semantics) 를 기반으로 발전시킨 프로그래밍 언어
    • 목표는 기존 C 프로그래머에게 익숙한 형태를 유지하면서 언어를 진화시키는 것
  • 정확하고 목적 지향적인 연산자 오버로딩을 지원
    • C++의 복잡한 오버로딩 구조 없이 벡터, 행렬, 고정소수점 연산을 자연스럽게 표현 가능
  • 계약 기반 프로그래밍을 지원해 런타임과 컴파일 타임 제약을 명시 가능
    • 코드의 안정성과 명세 일관성을 강화
  • Result 기반 오류 처리예외(exception) 의 장점을 결합
    • C 코드와 자연스럽게 통합되는 오류 관리 구조 제공
  • 타입 정보 조회(type introspection) 를 컴파일 타임과 런타임 모두에서 지원
  • 인라인 어셈블리 : 문자열이나 복잡한 제약 없이 일반 코드처럼 어셈블리 작성 가능
  • 디버그 모드에서 런타임 경계 검사(bound checks)값 검사(value checks) 를 자동 삽입
  • C3 표준 라이브러리는 디버그 빌드에서 상세 스택트레이스를 기본 제공
    • 단순한 “segmentation fault” 대신 구체적 오류 위치 확인 가능

Ergonomics and Safety

  • Optionals을 통해 에러와 null 처리의 안전성 제공
  • defer 문법으로 자원 정리 자동화 지원
  • slices와 foreach로 안전한 반복 처리 가능
  • 주석 기반 contracts로 코드 제약 조건 명시 가능
  • @pool 컨텍스트에서 메모리 자동 해제 지원

Performance by default

  • SIMD 벡터를 직접 작성해 하드웨어 수준 제어 가능
  • 다양한 메모리 할당자 선택으로 성능 미세 조정 지원
  • 오류 처리에서 오버헤드 없는 설계 채택
  • 빠른 컴파일 시간과 LLVM 백엔드 최적화 활용
  • 사용이 쉬운 인라인 어셈블리 제공

Batteries included standard library

  • 동적 컨테이너와 문자열을 포함한 표준 자료구조 제공
  • 크로스 플랫폼 추상화로 플랫폼 간 이식성 확보
  • 필요 시 네이티브 플랫폼 접근 허용

Leverage existing C or C++ libraries

  • C3는 C ABI와 완전 호환되어 별도의 “C 호환 타입”이나 함수 선언이 필요 없음
  • C3에서 C 코드 링크 가능하며, C에서도 C3 코드 링크 가능

Modules are simple

  • 단순하고 직관적인 모듈 시스템
    • 기본 설정이 합리적으로 구성되어 개발 흐름을 방해하지 않음
  • 모듈을 통한 네임스페이스 관리 제공
  • 명시적 제어로 캡슐화 구조 단순화
  • 인터페이스로 공유 동작 정의 가능
  • 제네릭 타입 생성을 단순하고 명확하게 구현할 수 있는 generic modules 기능 제공
  • 구조체 서브타이핑을 통한 구조 재사용 지원

Macros without a PhD

  • 컴파일 타임 매크로를 일반 함수와 유사한 형태로 작성 가능
  • 코드의 타입 정보를 이해하는 타입 인식 매크로 지원
  • C의 전처리기보다 명확하고 강력한 코드 생성 지원

Zig가 매년 breaking changes를 가져 오다보니, 언어는 마음에 들지만 이제는 손이 안 가더라구요.
반면 c3의 소개를 보니, 전체적으로 c + go 느낌이라 읽고 쓰기가 편하고, 판올림으로부터의 스트레스가 훨씬 적을 것 같은 느낌이네요.

후원도 좀 하면서... 최근 사용하고 있는데 재밌습니다.
C 하면서 불편한 점만 개선하려는 느낌이라 좋아요.
공식 문서가 좀 성숙하지 못하고
(이런저런 기능 알아보려면 뜬금없는 곳에 서술된 경우 많움...)

Hacker News 의견들
  • 나는 C3의 설계 철학의 절제된 방향성이 마음에 듦
    새로운 메모리 모델을 강요하지도 않고, C++처럼 되려 하지도 않음
    특히 완전한 ABI 호환성 덕분에 기존 C 빌드 시스템에 그대로 C3 파일을 섞어 쓸 수 있어 바인딩 작성이 필요 없어짐
    혁명보다는 진화를 추구하는 유지자의 비전에 박수를 보냄
    주말에 배워볼 언어로 추천할 만함. C99보다 현대적이지만 익숙한 느낌임
    • C3로 라이브러리를 작성해서 심볼을 내보내 바인딩에서 쓸 수 있는지 궁금함
      내가 C를 완전히 포기하지 못하는 이유는 cstring과 해제되지 않은 포인터 때문임
    • 완전한 ABI 호환성이 정말 중요한가 의문임
      C 자체가 위험한 언어라기보다 구현과 ABI가 위험한 것임
      fat pointer, varargs 개선, UBSan, MTE 등을 적용하면 꽤 괜찮아짐
  • C3 공식 문서의 Contracts 섹션을 읽다가 의문이 생김
    컴파일러가 계약을 반드시 검사하지 않아도 되고, 위반 시 정의되지 않은 동작이 될 수 있다면, 이걸 어떻게 신뢰하고 써야 하는지 모르겠음
    멋진 기능이지만 다소 위험해 보임
    • 계약은 “항상 참이어야 하는 조건”을 표현하는 불변식(invariant)
      이를 무시하거나, 런타임에서 검사하거나, 혹은 항상 참이라고 가정해 최적화에 활용할 수 있음
      예를 들어 포인터 유효성은 검사하고, 홀수 입력 조건은 가정으로 두는 식으로 선택 가능함
    • 계약은 의도를 표준화된 방식으로 표현하게 해주는 수단임
      대형 팀은 강제할 수 있고, Visual Studio 같은 툴은 경고만 띄우며 점진적으로 학습할 수 있게 함
    • 문서의 세 문장은 각각
      1. 컴파일러가 계약을 반드시 사용할 필요는 없음
      2. 위반 시 정의되지 않은 동작이 될 수 있음
      3. 안전 모드에서는 런타임 assert로 검사함
        즉, 개발 중엔 켜고, 배포 시엔 꺼서 성능에 영향이 없게 할 수 있음
    • 결국 컴파일러가 이미 하는 가정 기반 최적화를 코드 안에서 명시적으로 표현하는 것임
    • 계약은 “거의 도달하지 않을 조건”을 표현하는 부드러운 제약으로 이해함
      반드시 검사해야 하는 조건은 함수 내부에서 직접 코드로 처리해야 함
  • C3 GitHub 저장소에 자세한 내용이 있음
    C와 다른 점으로는 헤더 파일 없음, 모듈 기반 네임스페이스, 슬라이스, 연산자 오버로딩, 제네릭 모듈, Result 기반 오류 처리, 안전 모드의 런타임 검사 등이 있음
    • 기능은 좋지만 다소 불균형한 구성처럼 느껴짐
      개인적으로 함수 오버로딩, 기본 매개변수, 튜플 반환이 아쉬움
  • C3에서 ResultExpectedOptional이라 부르는 게 혼란스러움
    “T 또는 비어 있음”이 아니라 “T 또는 E”를 의미해야 하는데 이름이 잘못된 듯함
    관련 문서 링크
    • C3의 Optional은 Option<T>Result<T, E>와 다름
      에러 타입이 정수 코드 하나로 제한되어 있고, 이는 “진화, 혁명 아님” 철학에 잘 맞음
      type? 문법도 직관적임
    • 코드에서 “Optional”이라는 단어를 직접 쓰지 않음
      C의 의미를 유지하면서 out param의 부담을 줄인 설계임
    • 개념 이름을 임의로 바꾸는 건 별로지만, 둘 중 하나만 지원한다면 Optional이 더 명확한 이름임
      Result는 이미 일반적인 반환값의 의미를 가지므로 혼동될 수 있음
    • 그래도 “Option”이나 “Maybe”는 다른 의미이므로 “Result”나 “Either”가 더 적절하다고 생각함
  • Tsoding이 C3로 30시간 넘게 라이브스트리밍한 영상이 있음
    YouTube 재생목록
  • 나는 C3, Odin, Zig의 개발자들과 교류한 적이 있음
    세 언어가 경쟁하기보다 서로의 트레이드오프를 공유하며 배우는 관계라는 점이 인상적이었음
    • 임베디드 환경에서는 어떤 언어가 가장 합리적인지 궁금함
    • “경쟁이 아니라 학습”이라지만, 결국 표현만 공손한 경쟁 아닌가 하는 생각도 듦
  • 문서를 훑어보니 두 가지 궁금증이 해결됨
    1. LLVM 기반이라 이식성이 높음
    2. Tagged enum은 미지원
      대신 매크로와 리플렉션 같은 기능이 추가됨
    • Tagged union은 시스템 언어에서는 비효율적이라 생각함
      가장 큰 타입만큼 메모리를 차지하고, 런타임 타입 검사로 흐름이 옮겨가므로 정적 타입 언어의 장점을 잃게 됨
      필요할 때 직접 구현하는 편이 낫다고 봄
  • 언어를 새로 만드는 게 언제쯤 가치가 있을까 고민함
    C에서 제네릭, 슬라이스, 오류 전파를 직접 구현했지만, 컴파일러 제작은 너무 복잡
    그래서 나는 C 변형과 Go를 병행함
    • LLVM 덕분에 “더 나은 C” 계열 언어를 만드는 게 생각보다 쉬움
      하루 만에 프로토타입을 만들 수도 있을 정도로 진입 장벽이 낮음
    • 언어를 만드는 건 언제나 가치 있음
      새로운 패러다임을 현실로 만드는 유일한 방법
      언어는 문법, 표준 라이브러리, 툴링, 런타임까지 모두 조율해야 하므로 어렵지만, 그만큼 미래에 미치는 영향이 큼
    • C3는 원래 C2에 기여하던 Christoffer가 개발 속도에 답답함을 느껴 독립적으로 시작한 프로젝트임
      LLVM 덕분에 새로운 컴파일러를 직접 만들 수 있었음
    • 언어의 가치는 타인과의 공유된 이해를 만드는 데 있음
      혼자 쓰는 C 변형은 괜찮지만, 다른 사람과 협업하거나 외부 라이브러리를 쓰려면 공통 언어가 필요함
  • 처음엔 단순한 언어일 줄 알았는데, 의외로 풍부한 기능 목록에 놀람
    그리고 예외를 “Excuses”라고 부르는 점이 귀엽고 재치 있음
  • 이런 웹사이트야말로 프로그래밍 언어 사이트의 모범이라 생각함
    • 반대로, 디자인이 유치하고 아마추어스럽게 느껴졌음
      특히 내비게이션에 Discord 링크가 있는 게 그 인상을 강화함