Want to try C! right now? The browser playground lets you write, compile, and run C! code instantly — no installation required. 10 interactive examples including 3D graphics, actors, and smart contracts.
Installation
The C! compiler (cb) can be installed on macOS, Linux, and Windows. Choose the method that works best for you.
Quick Install (Recommended)
Run the install script to get the latest stable version:
# macOS / Linux curl -fsSL https://c-bang.integsec.com/install.sh | sh # Windows (PowerShell) irm https://c-bang.integsec.com/install.ps1 | iex
Build from Source
If you prefer to build from source or want to contribute to the compiler:
git clone https://github.com/integsec/C-Bang.git cd c-bang make install
Verify Installation
cb --version # C! compiler v0.1.0 (c-bang 2025)
Your First Project
Create a new C! project using the cb init command:
cb init my-project cd my-project
This creates a project with the following structure:
my-project/ cb.toml # Project configuration src/ main.cb # Entry point tests/ main_test.cb
Hello, World!
Open src/main.cb and you will see the generated starter code:
#[intent("Application entry point")] fn main() { println("Hello, C! world!") }
Build and run it:
cb run # Hello, C! world!
Variables & Types
C! uses let for immutable bindings and let mut for mutable ones. Types are inferred but can be annotated explicitly.
// Immutable binding (default) let name = "Alice" let age: u32 = 30 // Mutable binding let mut counter = 0 counter += 1 // Refined types with constraints let port: u16{range: 1024..65535} = 8080 // Sum types let result: Result<String, Error> = Ok("success")
No null, ever. C! has no null or nil value. Use Option<T> (which is Some(T) | None) when a value might be absent. The compiler enforces you handle both cases.
Functions
Functions are defined with fn. Parameters have explicit types, and the return type follows the -> arrow.
#[intent("Calculate the area of a rectangle")] #[pre(width > 0 && height > 0)] #[post(result == width * height)] fn area(width: f64, height: f64) -> f64 { width * height } // Generic functions fn first<T>(items: Vec<T>) -> Option<T> { match items.len() { 0 => None, _ => Some(items[0]), } }
Ownership & Linear Types
This is the most important concept in C!. Every value has an ownership qualifier that determines how it can be used:
| Qualifier | Meaning | Use count |
|---|---|---|
own |
Linear ownership — value is consumed on use | Exactly once |
borrow |
Affine — can be used at most once, safe to drop | At most once |
& |
Shared immutable reference | Unlimited reads |
&mut |
Exclusive mutable reference | One writer, no readers |
// 'own' means this function consumes the file handle fn close_file(f: own File) { f.flush(); f.close(); // f is consumed } fn example() { let file = open("data.txt"); close_file(file); // file can no longer be used here // file.read() <-- COMPILE ERROR }
Why this matters: Linear types eliminate entire vulnerability classes. Use-after-free? Impossible — the compiler won't let you use a consumed value. Resource leak? Impossible — the compiler won't let you forget to use a linear value. Double-spend? Impossible — you literally cannot use a token twice.
Intent Annotations
Intent annotations describe what your code should do. They serve two purposes: AI readability and formal verification.
#[intent("Sort a list of numbers in ascending order")] #[post(result.is_sorted())] #[post(result.len() == input.len())] fn sort(input: Vec<i64>) -> Vec<i64> { // AI can generate the implementation // Compiler verifies it satisfies the postconditions input.merge_sort() }
Available annotation types:
#[intent("...")]— Natural-language description of purpose#[pre(condition)]— Precondition that must hold before execution#[post(condition)]— Postcondition that must hold after execution#[invariant(condition)]— Condition that must hold throughout execution
Building & Running
The cb command-line tool handles building, running, and testing:
# Build for native target cb build # Build and run cb run # Run tests cb test # Build for WebAssembly cb build --target wasm # Build smart contract cb build --target evm # Format code cb fmt # Check without building cb check
Compile to Different Targets
C! supports five compilation targets. Use the --target flag to choose your output format:
# JavaScript (default) cbang build hello.cb # WebAssembly (WASI compatible) cbang build --target wasm hello.cb # LLVM IR (compile to native via LLVM) cbang build --target llvm hello.cb # EVM bytecode (Ethereum smart contracts) cbang build --target evm contract.cb # NEAR WASM (NEAR Protocol contracts) cbang build --target near contract.cb
Same code, multiple targets. Your C! source compiles to any target without changes. Shared types across frontend, backend, and smart contracts mean zero schema drift.
Compile to Native Binaries via LLVM
The LLVM target produces .ll files (LLVM IR) that you can compile to native binaries for any platform. This gives you maximum performance for servers, CLI tools, and system utilities.
Prerequisites
Install LLVM and Clang on your system:
# Linux (Debian/Ubuntu) sudo apt install llvm clang # macOS brew install llvm # Windows — download from https://llvm.org/builds/
Step-by-Step: C! Source to Native Binary
Start with a simple program:
#[intent("Application entry point")] fn main() { println("Hello from native C!") }
Compile to LLVM IR, then to a native binary:
# Step 1: Compile C! to LLVM IR cbang build --target llvm hello.cb # produces hello.ll # Step 2: Compile to native binary # Linux / macOS llc hello.ll -o hello.o -filetype=obj && clang hello.o -o hello # Windows llc hello.ll -o hello.obj -filetype=obj && clang hello.obj -o hello.exe # Step 3: Run the native binary ./hello # Hello from native C!
Quick test with the LLVM interpreter. You can skip the compile step and run LLVM IR directly: lli hello.ll
Next Steps
Now that you have the basics, explore these resources to deepen your understanding: