6 ms·
Zig, a language which is explicitly aimed at the same domain as C, has an improved semantics for all of these things. If a pointer can be null, it must be an o
by samatman 2y ago
Zig, a language which is explicitly aimed at the same domain as C, has an improved semantics for all of these things.
If a pointer can be null, it must be an optional pointer, and you must in fact check before you dereference it. This is what you want. Is it ok to write a program which segfaults at random because you didn't check for a pointer which can be null? Of course not. If you don't null-check the return value of e.g. malloc, your program is invalid.
But the benefit is in the other direction. Careful C checks for null before using a pointer, and keeping track of whether null has been checked is a manual process. This results in redundant null checks if you can't statically prove (by staring at the code and thinking very hard) that it isn't null. So in practice you're likely to have a combination of not checking and getting burned, and checking a pointer which was already checked. To do otherwise you have to understand the complete call graph, this is infeasible.
Zig doesn't do any of this. If it's a pointer, you can safely dereference it. If it's an optional pointer, you must check, and then: it's a pointer. Safe to pass down the call stack and freely use. If you want C behavior you can always YOLO and just say `yoloptr.?.*`.
Overflow addition and divide by zero are safety checked undefined behavior, a critical concept in the specification. They will panic with a stack trace in debug and ReleaseSafe mode, and blow demons out of your nose in ReleaseFast and ReleaseSmall modes. There's also +% for guaranteed wraparound twos-complement overflow, and +| for saturating addition. Also `@addWithOverflow` if your jam is checking the overflow bit. Unwrapping an optional without checking it is also safety-checked UB: if you were wrong about the assumption that the payload carries a value, you'll get a panic and stack trace on the line where you did `yolo.?`.
Shift operations require that the right hand side of the shift be a type log2(Type.bitwidth) of the left hand side. Zig allows integers of any width, so for a: u64, calling a << b requires that b be a u6 or smaller. Which is fine: if you know values will be within 0..63, you declare them u6, and if you want to shift on a byte, you truncate it: you were going to mask it anyway, right? Zig simply refuses to let you forget this. Addition of two u6 is just as fast as addition of the underlying bytes because of, you got it, safety-checked undefined behavior. In release mode it will just do what the chip does.
There's a common theme here: some things require undefined behavior for performance. Zig does what it can to crash your program if that behavior is exhibited while you're developing it. Other things require that you take some well-defined actions or you'll get UB: Zig tracks those in the type system.
You'll note that undefined behavior is very much a part of the Zig specification, for the same reasons as in C. But that's not a great excuse to make staying within the boundaries of defined behavior as pointlessly difficult as it is in C.
- fooker 2y agoYes, you can surely improve things from C. C is not a benchmark for anything other than footguns per line of code. The debug modes you mention are also available in various forms in C and C++ compilers. For example ASan and UBSan in clang will do exactly what you have described. The question is, then whether these belong in the language specification or left to individual tools.
- pjmlp 2y agoAs proven multiple times throughout the computing history, individual tools are optional, and as such used less often than they actually should be. Language specification is unavoidable when using said language.
- lstodd 2y agomwahahaha. as if there is some divine "language specification" which all compilers adhere to on pain of eternal damnation. no such thing ever existed.
- pjmlp 2y agoGiven that one can write Fortran in any language, maybe you're right.
- fooker 2y agoHave you wondered why Rust or Python do not have a specification? For a bunch of languages outside the C-centric world, specifications don't exist.
- pjmlp 2y agoThe certainly have, even if it isn't a ISO one. https://docs.python.org/3/reference/index.html https://docs.python.org/3/reference/index.html https://docs.python.org/3/library/index.html https://docs.python.org/3/library/index.html https://doc.rust-lang.org/reference/index.html https://doc.rust-lang.org/reference/index.html https://doc.rust-lang.org/std/index.html https://doc.rust-lang.org/std/index.html https://ferrous-systems.com/blog/ferrocene-language-specification/ https://ferrous-systems.com/blog/ferrocene-language-specific...