Live data from Hacker News

Problems of C, and how Zig addresses them

avestura.dev

11–20 of 290 posts

Re: Problems of C, and how Zig addresses them

#11
post #5

OK, so Zig to C is like Typescript to Javascript.

I don't think I fully understand the analogy.

Typescript has almost identical semantics to Javascript but adds typing syntax to improve developer experience and make it easier to manage a large-scale JS codebase.

Zig is a fundamentally different language than C that has a lot of new features. Two great examples are comptime and allocators which have complements in C, but are really very different from what C provides.

If you're suggesting that zig is aiming to provide a C alternative with better ergonomics, then I agree; but zig and C have a lot more differences than Typescript and Javascript.

Re: Problems of C, and how Zig addresses them

#13

I'm no expert on either languages, but I tried Zig for the first time properly the other day. I really liked it up until I hit hashmaps. One thing that I think goes under-appreciated about C (and other languages with a similar paradigm) is thats its pretty upfront and clear about what it can and can't do out of the box. If you want hashmaps in C, you need to create your own implementation, otherwise think of a way ro…

Would you mind elaborating on the complications you ran into? I ask because I think you used std.HashMap instead of std.AutoHashMap, the latter of which automatically chooses a hash function based on the types provided.

It was a little over a week ago now so my memory is a bit hazy, but I'll try to the best of my knowledge.

Without getting into the weeds of why (happy to do so, just want to keep this readable), basically I needed to define and populate a hashmap in a new script and then import it into my main script, which to my mind left me with two options:

* Define and initialise it at the same time (my preferred method) as a constant. I don't have much to say on this as iirc, I had no luck with it at all, never even got close.

* Define it in a (public) function, add each field in with "put" and then return the hashmap. I tried with std.AutoHashMap and various other things, but to what I could work out there was no type of hashmap, so it wouldn't accept my return type.

Re: Problems of C, and how Zig addresses them

#14

I think it should be const x: i16 = -1 * 32768; // valid In the text it's i32

That explanation is bogus anyway. It's a unary operator applied to a positive integer literal. No multiplication involved. In this case the range issue can be addressed in C by using the "L" suffix to upgrade the literal to 32-bit and let the compiler truncate it back to 16-bit.

Re: Problems of C, and how Zig addresses them

#16
post #9

That was a nice, clear explanation that even I could understand. One thing I wasn't sure about, though. var arr = [_]u32{ 1, 2, 3, 4, 5, 6 }; // 1, 2, 3, 4, 5, 6 const slice1 = arr[1..5]; // 2, 3, 4, 5 const slice2 = slice1[1..3]; If I were to use indices out of range, presumably that would that give me a compile time error? Could I use variables as the indices and, if so, could I get a seg fault at runtime or are th…

> If I were to use indices out of range, presumably that would that give me a compile time error?

Yes, if all operands are comptime-known (or comptime-length-known), bounds checks happen eagerly at compile time.

> Could I use variables as the indices and, if so, could I get a seg fault at runtime or are there some sort of guards on there?

Yes you can use variables. If they're out of range, behavior depends on the build mode:

- In Debug and ReleaseSafe, you get a guaranteed panic (which aborts the app with a stack trace)

- In ReleaseSmall and ReleaseFast, you get undefined behavior

On their discord I suggested a version of slicing that bounds checks in all modes (something like `slice?[1..5]`, syntax doesn't matter) and returns an optional slice, which is null if the bounds are out of range. But they didn't seem too keen on it. So I've been using a little wrapper function instead.

Re: Problems of C, and how Zig addresses them

#17
post #9

That was a nice, clear explanation that even I could understand. One thing I wasn't sure about, though. var arr = [_]u32{ 1, 2, 3, 4, 5, 6 }; // 1, 2, 3, 4, 5, 6 const slice1 = arr[1..5]; // 2, 3, 4, 5 const slice2 = slice1[1..3]; If I were to use indices out of range, presumably that would that give me a compile time error? Could I use variables as the indices and, if so, could I get a seg fault at runtime or are th…

Zig has bounds checking built-in. You can decide to remove it if you compile for ReleaseSafe instead of ReleaseFast, but it's always in debug builds.

Re: Problems of C, and how Zig addresses them

#18
Tangentially... I'm grateful that these new batches of systems languages have chosen to use the u8, i32, etc, style integer types. Rather than the uint8_t and int32_t style. First thing I do in any of my low level embedded C projects is put in the various uNN/iNN types.

Re: Problems of C, and how Zig addresses them

#19

Earlier quoted context omitted.

Would you mind elaborating on the complications you ran into? I ask because I think you used std.HashMap instead of std.AutoHashMap, the latter of which automatically chooses a hash function based on the types provided.

It was a little over a week ago now so my memory is a bit hazy, but I'll try to the best of my knowledge. Without getting into the weeds of why (happy to do so, just want to keep this readable), basically I needed to define and populate a hashmap in a new script and then import it into my main script, which to my mind left me with two options: * Define and initialise it at the same time (my preferred method) as a con…

Here's how you return a hashmap from a function:

  fn buildMap(allocator: std.mem.Allocator) !std.AutoHashMap(u64, u64) {
      var result = std.AutoHashMap(u64, u64).init(allocator);
      errdefer result.deinit();
      try result.put(10, 100);
      try result.put(20, 200);
      return result;
  }
Your #1 option should be possible once Zig has comptime allocators -- it's on the roadmap, but not possible yet iirc.

Re: Problems of C, and how Zig addresses them

#20
post #9

That was a nice, clear explanation that even I could understand. One thing I wasn't sure about, though. var arr = [_]u32{ 1, 2, 3, 4, 5, 6 }; // 1, 2, 3, 4, 5, 6 const slice1 = arr[1..5]; // 2, 3, 4, 5 const slice2 = slice1[1..3]; If I were to use indices out of range, presumably that would that give me a compile time error? Could I use variables as the indices and, if so, could I get a seg fault at runtime or are th…

Slices in zig are a fat pointer with a runtime known length, which have bounds checking at runtime and will panic if you access out of bounds.

Unless you build in releasefast, which disables that check. There is releasesafe for a release build that keeps bounds checking panics.

Post reply on HN