13 ms·
An intro to Zig's integer casting for C programmers
- friend-monoid 5y agoAs a C programmer, I have definitely shot myself in the foot in the conversions between types on multiple occasions. This is a really welcome feature.
- logicchains 5y agoIt says Zig eliminates "implicit conversions unless they are guaranteed to be safe (for example, assigning a u8 value to a u16 variable cannot fail or lose data)", but then suggests that @as should be used when "casting an int to a larger-size int of the same sign". Why should @as be used if it's safe to implicitly convert?
- flohofwoe 5y agoHmm, this indeed doesn't make much sense. Assigning to a wider type with or without different signedness doesn't require a cast as long as all bits fit into the new type: https://www.godbolt.org/z/x8a65sPcr https://www.godbolt.org/z/x8a65sPcr
- AndresNavarro 5y agoWhat I took from the article is that it's useful when combined with type inference. So in Zig you could do: var x : u8 = 5; var y = @as(u32, x); OR var x : u8 = 5; var y : u32 = x; The cast is needed in the first case to force the inference y: u32, otherwise it would be y: u8
- lionkor 5y ago> If runtime safety is turned off, you get undefined behavior You already know someone will teach their students to always have it off because its "slower" or something. Make something idiot-proof and the world invents a better idiot. Another language that does safety like this incredibly well is Ada (Ada/SPARK), and I'm unsure why people aren't more hyped about it. So many people hype Rust or Zig or whatever new language, and yet there's an incredibly safe and expressive language that's used in high-reliability applications like missile guidance systems, that nobody seems to talk about.
- pjmlp 5y agoOr Modula-2, NEWP, BASIC, or really most languages that aren't copy paste compatibel with C. Ada suffered from its domain, original price of compilers, and the few UNIX vendors that cared to offer compiler like Sun, it was an additional acquisiation on top of UNIX SDK. Everyone knows that only newbies do coding errors in C, so why spend the extra money? /s
- qayxc 5y ago> Everyone knows that only newbies do coding errors in C, so why spend the extra money? /s The Ariane 5 maiden flight disaster illustrated quite clearly that the choice of language has little influence on the actual correctness of a program. Ada on its own is no better than Pascal in that regard. A formally verified and thoroughly tested MISRA C program can be safer and more correct than a sloppily written Ada program. So the question is indeed not as rhetorical as one might think - why spend the extra money indeed? Isn't it better spent on verification, testing, tooling and culture, which benefits the development regardless of programming language?
- pjmlp 5y agoAriane 5 error was caused by the remaining 30% programming errors when we leave out the 70% of software failures caused by C typical errors. So yes, it is quite worthy to reduce the amount of money spent in verification, testing, tooling and culture. The alternative is to just give up that programmers will never learn and just force verification at hardware level, like Google is doing on Android. "Memory Tagging for the Kernel: Tag-Based KASAN" https://www.youtube.com/watch?v=f-Rm7JFsJGI https://www.youtube.com/watch?v=f-Rm7JFsJGI Oracle on Solaris SPARC, https://docs.oracle.com/cd/E37838_01/html/E61059/gqajs.html https://docs.oracle.com/cd/E37838_01/html/E61059/gqajs.html Apple on iOS, https://developer.apple.com/documentation/security/preparing_your_app_to_work_with_pointer_authentication https://developer.apple.com/documentation/security/preparing... Microsoft on Azure Sphere, https://www.microsoft.com/security/blog/2020/11/17/meet-the-microsoft-pluton-processor-the-security-chip-designed-for-the-future-of-windows-pcs/ https://www.microsoft.com/security/blog/2020/11/17/meet-the-...
- flohofwoe 5y agoIME the strict conversion rules in Rust and Zig can be quite a bummer for somebody coming from C because they may add a surprising amount of friction in day-to-day coding. Yes, C code is often way too sloppy when it comes to picking the right type (signed vs unsigned vs float), and it conveniently hides the problems if the wrong choice was made. But sometimes the same value needs to be used in integer and floating-point math, and there is no single correct type for this value. There are also some tricky choices in bit twiddling operations. Is it really such a problem when bits are shifted out of a value when this is normal behaviour down on the assembly level? I guess I'll eventually learn to live with strict explicit conversion, and eventually I'll get better at picking the right type from the start, but I think implicit versus explicit conversion is an area where there is no "completely right" solution, because with 100% explicit conversions even coding down on the assembly level is more convenient ;)
- pjmlp 5y agoC programmers are well known to refer to such programming safety as straighjacket since the Pascal days anyway. There was more than enough time to learn why it was the right option to start with.
- lrfield 5y agoThe straight-jacket is the syntax in Ada. I don't feel locked in by the correctness measures, but if you are going to have elaborate declaration blocks I prefer "let foo = bar in ...". Because everything else is "let" in disguise. ML got the syntax right.
- pornel 5y agoRust does go overboard though, e.g. indexing requires `usize`. You either use `usize` for all your integers, or you end up with a cast-salad. arr[i as usize] This is actually risky, because even when you only meant to extend, you can also accidentally truncate or change sign. `as` does all of these things without a warning, and mixed with type inference it can easily lead to surprises. Rust makes it worse by insisting on a theoretical support for 16-bit and 128-bit `usize` regardless of the target platform, so you can't use `a[i.into()]` to infallibly convert `u32` to `usize` on 32-bit and 64-bit platforms. The correct syntax is: arr[usize::try_from(i).unwrap()] which is painfully verbose. In larger expressions it's almost an obfuscation of what the code is actually doing.
- bla3 5y ago> You won't even get a warning unless -Wextra or -Weverything is turned on. That's because -Wconversion isn't part of -Wextra for some reason. It is part of -Weverything though, and with that clang does warn: warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion] if (sizeof(int) < -1) abort(); ~ ^~
- deleted 5y ago[deleted]
- gher-shyu3i 5y agoZig is shaping up to be a very nice language. It has some very cool ideas. I hope we'll see more of it at a larger scale.
- scoutt 5y agoI am curious to know the reasons behind the @as() syntax. What's wrong with "i32 y = (i32) x;"? I look with interest to new languages but after so many years dealing with C, my parser crashes when I see the type after the variable name and at the end of functions declarations. var x : u8 = 5; What's wrong with "u8 x = 5;"? And I don't really like type inference very much (or when it's abused or cannot be avoided). What is "b"? Oh, I have to check what it's being casted from... var a: u8 = 255; var b = 1 + 2 + 3 - (4 + @as(i32, a)); What type is "b"? i32? Curious fact: the above code generates >40000 lines of assembly in godbolt: https://www.godbolt.org/z/fxfbb9jfn https://www.godbolt.org/z/fxfbb9jfn
- dnautics 5y ago> What's wrong with "u8 x = 5;"? I believe it makes the parser marginally more complicated. Let's say you had a non-builtin type, "foo". The var trigger immediately declares what's going on. For "foo x = 5;" the parser must either 1) have contextual information that foo is a declared type or 2) wait to notice that there are two identifiers side-by-side and then resolve that this means "it must be a variable declaration". Honestly, C and C++ are very much in the minority for choosing this syntax. Coming form pascal, I remember finding this syntax to be annoying 20 years ago, so it's my bias to believe that this is just internalized pain for C devs. As for the type coercion with the () operator... well, C is infamous for "spiral types". Typecasting complicated things in C, like, say, an array of pointers, can get scary as hell.
- Someone 5y agoA bit more than marginally more complicated, if you consider the cases of parsing partial or incorrect programs. You want to be able to (somewhat) parse those so that you can syntax-colour, auto-complete, and mark errors in a code editor. I think those are the major reasons modern languages don’t do such things the C way.
- scoutt 5y ago> I believe it makes the parser marginally more complicated This would mean that the "peace of mind" of the Zig compiler developer has priority over my own "peace of mind". That's not ok. Is the compile developer reasoning "I don't care if the syntax is verbose, messy (or whatever), it just makes my job easier"? > Honestly, C and C++ are very much in the minority for choosing this syntax Java, C#, Objective-C....
- Shadonototro 5y agocasting, one of the reason i gave up with Zig quickly, it just is painful and solves nothing, it makes the code hard to decipher
- losvedir 5y agoHow quickly? Like, you saw it in the docs when you were mildly interested and decided it wasn't for you? Or you started a project, had at least a "hello world" compiling, but then eventually gave up on it because you were tired of casting? In that case I'm curious what the project was since I haven't run into casting all that often, but it might vary by domain.
- dnautics 5y agoi just looked over some code I have which takes a complicated 3rd party binary format, parses, and extracts information from it. In about 2K LOC including tests there are no casting events except for some int-to-pointer and pointer-to-int at the boundary of passing reference to WASM.
- Shadonototro 5y agoIt was a while ago, a game engine, it just feels bad, maybe i misused the language, but that is a sign things aren't intuitive Some people love typing code like they'd write books, i don't, i like to be concise and to go straight to the point And it's not just as(i32) intToFloat(f32) floatToInt(i32), and then between i8 i32 i64, and then bitwise operations, and then slices, and then C strings etc etc etc, lot of visual bloat
- AnIdiotOnTheNet 5y agoI like it because it provides explicitness and readability. There is no guessing or following a flow chart of implicit type conversions to see what's going on.
- veltas 5y ago>You won't even get a warning unless -Wextra or -Weverything is turned on. I know people are used to languages where compiler warnings are on by default, but if you are building C without -W/-Wextra you are kind of asking for trouble. -Weverything is probably too pedantic for most people but -Wextra is pretty much required. And -Werror is required for projects where discipline can't be assumed or where the build log is bigger than a screenful.