Casting a slice of char to float

How to cast a slice of char to a float?

This errors:

    const i = someRuntimeComputation(); // will give 0 here in my example
    const from align(@alignOf(f32)) = [_]u8{ 1, 2, 3, 4 };
    const to: f32 = @bitCast(from[i..i + 4]); // []const u8

with:

error: cannot @bitCast from '[]const u8'

The index are runtime known so we get a slice. If this index had been comptime known, I would have ended up with an array and this is properly handled with .*.

Although @castholm works, it’s also worth having a look at @efjimm’s.

You can use std.mem.bytesAsValue to reinterpret a slice of bytes as a pointer to a value (which you can then dereference).

fn toFloat(bytes: []const u8) f32 {
    return std.mem.bytesAsValue(f32, bytes).*;
}

Note that bytes may be unaligned in this example. If alignment matters, you need to type that parameter as []align(@alignOf(f32)) const u8.

2 Likes

I should also add that you use @bitCast to reinterpret non-pointer values (e.g. f32 to u32), and @ptrCast or @ptrFromInt/@intFromPtr to reinterpret pointers. A slice counts as a pointer.

1 Like

Slicing an array gives you a slice, but you need an array to bitcast. Deferencing a slice with a comptime-known length will give you an array, like so:

const to: f32 = @bitCast(from[i..][0..4].*);
1 Like

I was thinking about your solution, isn’t it a limitation of zig? I mean from[i..i + 4] and from[i..][0..4] should really be the same. Sure i is a runtime value but the slice boundaries are relative to it.