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