# Working with C

One of the great features of Zig is that it is fully compatible with C. Let's return to the *Hello, world!* example, this time using C to print instead of Zig.

```zig
const c = @cImport({
    @cInclude("stdio.h");
});

pub fn main() !void {
    _ = c.printf("Hello, world!\n");
}
```

That's it! Using the `cImport` directive, we can directly use C code inside of Zig. Of course, please compile this to verify that it works as expected.

{% hint style="info" %}
For the rest of this page, we'll be working across multiple files. The filenames will be given in a comment that precedes the source code. Creating a new directory to store all these source files is encouraged, so that it doesn't get too messy.
{% endhint %}

## Custom C code

Let's write some of our own code instead of using the C standard library. Our custom C program will have just a single `greet` function, that says hello to the name passed as a parameter.&#x20;

```c
// In file /c-src/greeter.h

void greet(const char *name);

// In file /c-src/greeter.c

#include "greeter.h"
#include <stdio.h>

void greet(const char *name) {
  if (name == NULL) {
    printf("Hello, world!\n");
  } else {
    printf("Hello, %s!\n", name);
  }
}
```

Let's verify that this works as a C program first. We can create a temporary main file for the C program.

```c
// In file /c-src/main.c

#include "greeter.h"
#include <stdio.h>

int main() {
  greet("Alice");
  greet("Bob");
  greet(NULL);
  return 0;
}
```

And then compile it using `gcc` as with any other C program.

```bash
$ gcc -o greet c-src/greeter.c c-src/main.c  
$ ./greet
Hello, Alice!
Hello, Bob!
Hello, world!
```

It works! So how do we get `gcc` to work with Zig? Ah! We unveil the secret behind Zig's ability to handle C code so well. It *comes with a C compiler :O*

```bash
$ zig cc -o greet c-src/greeter.c c-src/main.c  
$ ./greet
Hello, Alice!
Hello, Bob!
Hello, world!
```

{% hint style="info" %}
Okay, if you're cheeky and try doing `zig cc --help`, you might discover that it's actually Clang (on a Macbook at least). But the creator of Zig actually [wrote about this](https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html), and TL;DR it is Clang but smaller and does more out-of-the-box.
{% endhint %}

Insane! Let's continue by trying using this C code in Zig instead of just C. We can start by modifying our build file to look for `greeter.h` in the correct place.

```zig
// In file /build.zig

const std = @import("std");

pub fn build(b: *std.Build) void {
    const exe = b.addExecutable(.{
        .name = "greet",
        .root_source_file = b.path("src/main.zig"),
        .target = b.standardTargetOptions(.{}),
        .optimize = b.standardOptimizeOption(.{}),
    });
    exe.addIncludePath(b.path("c-src"));

    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
}
```

Now, we can configure our `main.zig` file to import our custom `greeter.c`.

```zig
// In file /src/main.zig

const c = @cImport({
    @cInclude("greeter.c");
});

pub fn main() !void {
    c.greet("Alice");
    c.greet("Bob");
    c.greet(null);
}
```

We use the `zig build run` command instead of `zig run`, and we can see that everything works well!

```bash
$ zig build run
Hello, Alice!
Hello, Bob!
Hello, world!
```
