Why are c_int and similar builtin types?

What is the reason that the integer and float types for c compatibility are builtin types?

Is there a reason why evaluating them at comptime using switch statements on attributes of @import("builtin").target is not possible.

It’s totally possible to have them be defined in std.

However, c ffi is a first class feature so c types might have been added, at least partially, before that was possible.

Or andrew just didn’t think of it, or decided for some reason against it.

This is just guessing on my part.

Perhaps he, or another team member, will come to enlighten. us.

Just remembered, translate-c is a thing, the compiler can translate c to zig one to one, this requires either the types to be builtin, or std to receive (more) special treatment, which is something they want to minimise.

Also, some types can’t be defined in std such as c pointers [*c]T, no other pointer type in zig has the same semantics so there needs to be a dedicated one for translate-c since the compiler can’t know what constraints the pointers have.

Note that it’s recommended to avoid c pointers if you’re handwriting ffi/translating.

I edited the question above to only include number types. c pointers make sense to be builtin types.

The rules for the size of C integers are complex, zig integers are simpler.

C integers also have different UB rules. For example, unsigned integers in C will wrap, it’s undefined for signed integers in C to wrap. All implicit wraps in Zig integers are UB (aka illegal behaviour) for both signed and unsigned integers.

Without builtin C types, you would not get the same program behaviour between compiled C code and C code translated to Zig.

Edit: wording

5 Likes

If in zig an integer overflow is wrap or UB is not type-specific, but operator-specific. +% is wrapping, + causes UB. This is also true for c unsigned integers:

pub fn main() void {
    var a: c_uint = 0x80000000;
    _ = &a;
    const b: c_uint = a + a;
    _ = b;
}

(here an int in c has 32 bits)

panic: integer overflow

Compiled C code and C code translated to Zig having the same program behaviour, is not caused by some difference between c_uint and u32 (on targets on which c_uint has 32 bits), but by translate-c using + for signed integers and +% unsigned integers.

3 Likes

Oh cool, I didn’t realize that translate C would choose between + and +%, thanks for correcting/updating that for me.

AFAIU then, it’s just an integer sizing thing.

1 Like