Bitwise - Overtly set the 8th bit on a i8: Testing twoscompliment

Hi,

What is the correct way of setting the 8th bit to 1 overtly. Irrespective of the data type?
U8, I8 I don’t care. The 8th bit is to be set.

Try 1 - Let’s use an or

var my_i_byte1:i8 = 0;
my_i_byte1 |= 0b10000000;
std.debug.print("My_i_Byte1 is number {d}, \n", .{my_i_byte1} );

No, type ‘i8’ cannot represent integer value ‘128’
Clearly my binary number is being converted to a U8

Solution - But you have got to be kidding me

var my_i_byte1:i8 = 1;
my_i_byte1 <<= 7;
my_i_byte1 |= 0b01111111;
std.debug.print("My_i_Byte1 is number {d},\n", .{my_i_byte1} );

In this solution I start with a 1. Move it to the 8th position by shifting it to the left 7 times
and then use it. But there must be a better way.

Why do I want to do this?

I just wanted to ensure I had twos compliment right in my head. The best way to test this is to set the bits manually and ensure it comes to what you think it does eg 11111111 is -1

I just wondered if there was a better way. ie a “proper” OR, AND, NOT that does as it’s told.

Thanks in advance.

@bitCast: Documentation - The Zig Programming Language

2 Likes

Thanks. Works a treat.

const std = @import("std"); // this loads the standard library for zig

pub fn main() !void {

    {
    const my_u8:u8=0b1111_1111;                          // load the u8 up with 1111_1111
    const my_i8:i8=@bitCast(my_u8);                     // Copy over to i8
    std.debug.print("Is this -1 ? >{d}\n", .{my_i8} );  // check it's minus 1
    // output
    // Is this -1 ? >-1
    }

} // end of main


May I interest you in an Extremely Overengineered solution?

fn flipBit(v: anytype, b: comptime_int) @TypeOf(v) {
    const t_info = @typeInfo(@TypeOf(v));
    switch (t_info) {
        .Int => |i_info| {
            if (i_info.bits < b) {
                @compileError("value does not contain that bit");
            }
            if (i_info.signedness == .signed) {
                var u_v: @Type(std.builtin.Type{
                    .Int = .{
                        .bits = i_info.bits,
                        .signedness = .unsigned,
                    },
                }) = @bitCast(v);
                const flipper: @TypeOf(u_v) = 1 << b - 1;
                u_v |= flipper;
                return @bitCast(u_v);
            } else {
                const flipper: @TypeOf(v) = 1 << b - 1;
                return v | flipper;
            }
        },
        else => @compileError("can't flip a bit on a non-integer"),
    }
}

test "flip eighth bit" {
    const flipme: i8 = 5;
    std.debug.print("flipped: {d}\n", .{flipBit(flipme, 8)});
}
4 Likes

This is great when you’re being paid per lines of code. lol

2 Likes

But not if you’re being paid per instruction!

2 Likes

I 'll be nice and enable the ReleaseSafe mode: Compiler Explorer :slight_smile:

2 Likes

Right? Comptime safety beats runtime safety any day of the week.