Remix.run Logo
ozgrakkurt 3 hours ago

> Consider, for instance, bitcasting a [2]u8 to a u16. Under the old semantics, the result of this operation depends on the target endian: on big-endian targets, the first array element became the 8 most significant bits, whereas on little-endian targets, the first array element became the 8 least significant bits. Under the new semantics, because we only care about logical bit representation (which is endian-agnostic), the operation behaves identically on every target:

This is a huge mistake. You would never expect something like bitCast to do this.

I don't understand this approach. Why change something so simple and low level to be complicated and high level?

Just don't allow casting to u24, as it makes no sense unless you define u24 to be u32 sized as I think c standard does.

I think this approach as an idea is bad but at least just add another built-in that implements this higher level idea to not break a simple expectation and current behavior?

jjmarr 2 hours ago | parent | next [-]

> Just don't allow casting to u24, as it makes no sense unless you define u24 to be u32 sized as I think c standard does.

The reason u32->u24 casting must be well defined is because some hardware (e.g. many GPUs, microcontrollers) only have floating point multipliers. A 24 bit unsigned integer (stored in a 32 bit register) can be losslessly converted to a 32 bit float by the hardware, multiplied, then converted back.

This is much faster than doing 32 bit multiplication in software, however, you still need to tell the compiler about this constraint.

kevin_thibedeau an hour ago | parent | prev | next [-]

GCC has had __int24 for the AVR backend for some time. Useful for larger integers than int16_t while saving 25% over a 32-bit value. C23 does not mandate padding for _BitInt types. It is wrong to assume that will happen or is the optimal implementation for portable code.

boricj 2 hours ago | parent | prev | next [-]

If I understand it correctly, it basically boils down to copying bits from the source to the destination, in order from the least significant bit to the most significant bit. It's not equivalent to C++'s reinterpret_cast.

I'm no Zig expert, but if you want endian-dependent semantics I'd assume either @ptrCast or a packed union would do the job.

tremon 2 hours ago | parent [-]

But doesn't that show why this is a bad idea? If I understand correctly, this code:

  const MyUnion = packed union {
    full: u16,
    bytes: [2]u8,
  };
  const value: u16 = 0x55aa;
  const in_union: MyUnion = @bitCast(value);
  const without_union: [2]u8 = @bitCast(value);
  std.debug.assert(without_union[0] == in_union.bytes[0]);
  std.debug.assert(without_union[1] == in_union.bytes[1]);
...will now succeed or fail depending on the endianness of the target. That looks like the type of footgun that will bring decades of joy.
peesem an hour ago | parent | next [-]

zig does not allow arrays in packed structs/unions specifically for endianness reasons (there may be other reasons as well but endianness is what i know of)

AlienRobot an hour ago | parent | prev [-]

I wonder if packed union also got/will get the same "logical bits" treatment?

nvme0n1p1 3 hours ago | parent | prev | next [-]

You don't need to use @bitCast for the behavior you're talking about. @ptrCast still exists.

ozgrakkurt an hour ago | parent [-]

@ptrCast,

> Converts a pointer of one type to a pointer of another type. [1]

[1] https://ziglang.org/documentation/master/#toc-ptrCast

So it is not the same.

You could use it to define a function that implements bitCast. Which defeats the purpose of having any @bitCast intrinsic instead of using @mempcy for everything

tialaramex 3 hours ago | parent | prev | next [-]

> This is a huge mistake. You would never expect something like bitCast to do this.

Is there at least some sort of @transmute or something ? If Zig wants to say "bitCast" means this odd operation, but provides the thing most people actually want under some plausible name that's just an extra thing to learn which seems OK.

AlienRobot an hour ago | parent | prev | next [-]

To me it makes sense. If you don't know what endianness is, it doesn't make sense that a program you write in one programming language works for one target but doesn't work for the other.

I think endianness is the footgun that Zig is solving, rather than Zig being the one introducing a footgun when you deal with endianness.

2 hours ago | parent | prev [-]
[deleted]