…the documentation says " b must be comptime-known or have a type with log2 number of bits as a." This makes perfect sense. I have a b that is NOT comptime-known, and am having trouble. (Note: if I use a comptime-known value for b, all DOES work fine.) So, for example…
var j: u32 = 7;
j += 1;
const z: u32 = 0b1 << j;
Complains with “LHS of shift must be a fixed-width integer type, or RHS must be comptime-known”. I assume this means that 0b1 is not a fixed-width integer (?), so I try:
const z: u32 = @as(u32, 0b1) << j;
But this gives the more enigmatic “expected type ‘u5’, found ‘u32’” and “note: unsigned 5-bit int cannot represent all possible unsigned 32-bit values” … I’m not sure what type is considered only 5-bits wide, in this situation. I tried a few other things, but think I’ll leave it at this to see what help it might inspire.
In addition to the integer types above, arbitrary bit-width integers can be referenced by using an identifier of i or u followed by digits. For example, the identifier i7 refers to a signed 7-bit integer.
“…have a type with log2 number of bits as a” - I didn’t read this carefully enough, or internalize its meaning. It makes perfect sense that the care that must be taken is in making sure that b is not more than log2 the size of a. I was thinking of the need to make a BIG enough (which, it wasn’t, anyway, as my b was a u32 – even IF I was only using a few of the lowest bits) – the key here is to make sure that b is SMALL enough - limited in bit-size so that shifting doesn’t overflow a. All very clear now. Thank you all again!
When I run into this for the very first time, I also did not understand at all what the compiler wants with me Btw, see also this comment and the entire topic for the arbitrary width integers, it’s a really cool feature of Zig.
So, for completeness, here is a version that is closest to my OP version, with the least change necessary to accomplish the goal:
var j: u4 = 7;
j += 1;
const z = @as(u32, 0b1) << j;
So, importantly, my j (I should have called it b!) needed to be a u4, as that’s the sufficient number of bits to hold my final value of 8 (u3 would have been enough for the original value of 7). AND my a needed to be cast to a u32 (it’s not enough for z to be defined as a u32). This latter bit is what the LHS part of the error message tries to make clear:
LHS of shift must be a fixed-width integer type, or RHS must be comptime-known
It might help to make that message say the same thing as the documentation: “b must be comptime-known or have a type with log2 number of bits as a.” and perhaps the documentation could also declare that a must be (cast to) a fixed-width integer, big enough to hold a 0b1 shifted b bits (or, big enough to hold the number 2^b). Just two cents of thought.
Just wanted to mention another pattern, building off of what @dee0xeed shared. If you want to iterate over the entire range of an integer, you can write a loop like so:
const std = @import("std");
pub fn main() void {
const shiftee: u32 = 1;
var k: u5 = 0;
while (true) {
std.debug.print("{b}\n", .{shiftee << k});
k +%= 1
if (k == 0) break;
}
}
May not be relevant for the problem you were trying to solve this time, but I find this comes in handy.