(PS: it's probably ok because C compilers seem to accept redundant typedefs)
The only sane way to deal with name collisions is either to use C stdlib types in library APIs (e.g. uint8_t), or use a library specific prefix (e.g. mylib_u8) - which is of course even more awkward than just using the standard uint8_t.
Naming might go well and have the same utility, but you never know what evil things are going on in all those headers, redefining each other's symbols and yours.
In what world would an u32_MYLIB would be different than an u32_SOMELIB?
Basic types are common enough.
Also minor nitpick I have is that the interval/range syntax in zig is pretty confusing as it can be both inclusive and exclusive depending on context. Swift does it imo better by ... being inclusive and ..< exclusive
Zig programmers don't need to keep talking about types, so the type (and thus in this case its size) is getting mentioned mostly when that matters, e.g. API boundaries.
1. After 5 minutes, you know what sizes they are, and don't need reminding.
2. Easier to touch type.
3. They're just aesthetically more pleasing to the eye.
4. The names aren't really different, they follow the most-used (by far) sizes on C.
5. It's easier to say and hear them. I can say "int" when talking code with someone, instead of "eye-thirty-two".
6. I'm guessing it may be easier for a visually impaired coder with a screen reader.
There is nothing wrong with that reasoning. Also, there will never be a language which is perfect in every conceivable way, this is such a minor difference that if someone chooses a language over this alone, they are not being reasonable.
> Besides, they're just easier to touch type.
These two styles are equally fine for touch typing… as long as you know how to touch type (not just how to touch type on the alphabet rows).
D allows 4 bit types using conventional bit fields (but you can't take a pointer to them).
const std = @import("std");
const expectEqual = std.testing.expectEqual;
test "u4 is 1 byte" {
try expectEqual(1, @sizeOf(u4));
}
test "u4 is 4 bits" {
try expectEqual(4, @bitSizeOf(u4));
}
test "u4 is 1-byte-aligned" {
try expectEqual(1, @alignOf(u4));
}
test "pointers to u4 work like any other pointer type" {
var foo: u4 = 10;
const foo_p = &foo;
try expectEqual(@as(u4, 10), foo_p.*);
foo_p.* = 7;
try expectEqual(@as(u4, 7), foo);
}
Packed structs are Zig's replacement for bit fields: const std = @import("std");
const expectEqual = std.testing.expectEqual;
test "bool has a bit size of 1 bit, a size of 1 byte, and an alignment of 1 byte" {
try expectEqual(1, @bitSizeOf(bool));
try expectEqual(1, @sizeOf(bool));
try expectEqual(1, @alignOf(bool));
}
test "in a regular struct, fields are aligned to their natural alignment..." {
const Natural = struct {
read: bool,
write: bool,
exec: bool,
};
try expectEqual(3, @sizeOf(Natural));
try expectEqual(1, @alignOf(Natural));
}
test "...unless otherwise specified" {
const TwoByteAligned = struct {
read: bool align(2),
write: bool align(2),
exec: bool align(2),
};
try expectEqual(6, @sizeOf(TwoByteAligned));
try expectEqual(2, @alignOf(TwoByteAligned));
}
test "in a packed struct, fields occupy exactly their bit size" {
const Packed = packed struct {
read: bool,
write: bool,
exec: bool,
};
try expectEqual(3, @bitSizeOf(Packed));
try expectEqual(1, @sizeOf(Packed));
try expectEqual(1, @alignOf(Packed));
}Now maybe if you're already 64bit that's fine (it's unlikely that we'll ever need 128bit, and code is unlikely to grow down), but for anything starting smaller it's a pain.
Zig, like Rust, has two kinds of "primitive" numeric types, the kind which are an explicit size in bits (u8, i16, f64 and so on) and then the word size ones (isize, usize), which are whatever size is suitable for your target machine.
C gets this all muddled because it has named primitive numeric types but their meaning is imprecise, and then it uses a typedef to assign one of these (but you don't know which one) as the native word size. So maybe long is the same as your size_t, and C will just assume you know what you're doing when you write a long where you need a size_t - thus making your code non-portable.