Hello, I would like to start porting some of my C projects to Zig to see how it feels to program in this promising language. I did the same with Rust before and the following book helped a lot: Introduction · 30 minutes of Introduction to Rust for C++ programmers. As Ziglang positions itself as C eventual replacement I am curious if there is a similar guide written for C programmers learning Zig. If there is no guide perhaps somebody can point me to resources targeting people with C background. Thank you!
Hello @deafbeef Welcome to ziggit
The Zig Learning Resources is a collection of learning resources.
The first video: The Road to Zig 1.0 is a good starting point. Andrew Kelley presents how C was broken and how zig fixed it.
If you want a tutorial there is the amazing tutorials from @dude_the_builder dudethebuilder youtube channel.
I come also from a C background, so if I can give you some advice, is to use the standard library as a “tutorial”, zig std is actually very readable, which isn’t the case at all with C/C++ equivalent.
So personally most of what I’ve learned comes from this forum, and the zig compiler and it’s std. I would say that 90% of learning Zig from a C developer, comes from mapping how to translate C statements into Zig so it’s pretty easy since they both share very similar type primitive.
The main pain point is going to be pointers I would say, Zig has a variety of pointers, and ways of expressing different semantics, like slice which are a pointer and a length, pointer to one element, array, sentinel terminated array, optional pointers etc.
The second pain point is probably going to be that Zig enforces correctness (but since you have done things in Rust, this shouldn’t be a big deal to you), things that would be trivial in C like adding two integers of slightly different types, has to be done explicitly through the use of builtins unless they can coerce safely. so adding a u8 to a u64 is ok, but adding a u8 to a u7 is not, and your code has to reflect that explicitly.
Also one thing that was really confusing for me at first, was the fact that Zig is lazily evaluated, so if you don’t reference something, it doesn’t necessarily shows as an error, therefore I remember having no error report from the lsp when making a function and 30 minutes later when I actually start to reference it, it would complain and I used to be very confused by that.
But honestly if you did it in Rust, I think you will be fine with Zig. Be aware tho that the language is still breaking things quite often so maybe try to target a stable release.
A couple of years ago I studied D a bit and used this among other educational resources. It would be nice to have something similar for C->Zig.
The second half of this is often true, but not always. I would say that musl libc is one of the better codebases out there for learning deep/advanced C.
That comment is more C for Zig programmers though, so I’ll second the recommendation: reading the standard library is about the highest-payoff thing you can do to really learn the language, its idioms, naming conventions, and so on.
Thank you for a warm welcome, @dimdin ! Andrew’s video is very motivational. I admire him for taking such a monumental project.
Perfect! Thank you @dee0xeed It is exactly what I am looking for.
There is something similar for zig: LibC to Zig
Thank you, @pierrelgol , I am going through dudethebuilder’s tutorial right now. As a side effect I started to use Neovim and Nix package manager. In a way Neovim to vim is llke Zig to C Speaking of gotchas: I did not expect Zig to rely on compiler to decide if function parameter gets passed by value or reference without programmer’s consent to do so. For example Delphi Object Pascal used ‘const’ parameter decorator to indicate that compiler can make that decision. Coming from C it feels like giving too much control to the compiler I also slowly going through the std lib as a reference how things should be done.
The issue is still open.
It is a feature. Function arguments are read only in zig. Zig compiler decides to pass by value or by const *
.
The advantages are:
- The function code is more readable because you don’t have to dereference the arguments.
- You can have the same code run optimal at different architectures e.g. using by value for 64bit cpu and by reference for 8bit cpu.
And here comes constCast() builtin…
Nice, thank you, @chrboesch
I like Pascal ^
to designate pointers (C’s bit-wise XOR, oops).
But for some very strange reasons
This is because ^ isn’t ergonomic on all keyboard layouts.
that was not adopted in Zig.
Yes, but that’s an intentionally sharp object which is seldom needed.
No one should complain if they use @constCast
improperly and their program does weird things. It can easily undermine the soundness of code which uses it, in a way which should hopefully be apparent in the very name.
The “attack of the killer features” aliasing issue is a bit of a different story, but this is recognized as something which must be dealt with in the course of time. In the meantime it does call for paying careful attention to aliasing risks in the code we write.
Zig is in fine shape to write good programs, but is an immature, pre-1.0 language. I would argue that the state of reference semantics and result location resulting in the risk of collision is the most prominent example of that.
I’m fine with *
, personally, but if that’s a consideration, I have some bad news about {
and }
…
Yes, I understand why, pros and cons, I just did not expect such a “compiler magic” coming from C. Thank you for ‘constCast()’ tip!
You have got me curious, @mnemnion. After Modula2/Pascall my will was broken by years of C/C++ to the point that I am ok with ‘*’ vs ‘^’ . However I don’t like to type therefore I vote for {} vs begin/end. Anyway, I take you are joking…
Interesting, good to know!