0

I'd like to set a specific bit to 0 but without using a bitmask because I'm using enums and if the enum values change, enum fields get moved around then the bitmask would no longer be valid.

I can toggle a bit on, using a temporary variable then OR it with the already existing bitfield

#include <assert.h>

enum EState{
    k_EStateNone,// bit 1   - 1
    k_EStateFoo,//  bit 2   - 10
    k_EStateBar//   bit 3   - 100
};
uint64_t togglebiton(uint64_t state,EState ebit){
    uint64_t temp = 1<<ebit;
    state|=temp;
    return state;
}
int main(){
    uint64_t state = 0;
    state = togglebiton(state, k_EStateBar);
    state = togglebiton(state, k_EStateFoo);
    //foo bar = 110 == 6
    assert(state == 6);
    return 0;
}

But I'm unsure how to go about flipping the bit off, because I can't AND the whole thing with 0..

Kayla
  • 223
  • 2
  • 14

1 Answers1

1

To flip a bit off, first shift the bit to the desired location, then use a bitwise NOT to invert all bits so that all but the target bit is set, then do a bitwise AND.

uint64_t togglebitoff(uint64_t state,EState ebit){
    uint64_t temp = 1ULL<<ebit;
    state&=~temp;
    return state;
}

Also make sure that the constant you're shifting is of the correct type so that you don't shift into the sign bit of a signed type or more than the bit width of the type in question.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Ah! Thank you! That's exactly what I was looking for, I wasn't aware I could use `~` can you elaborate more on "shifting of the correct type"? Would that mean that EState would have to be of type uint64? – Kayla Jun 07 '22 at 01:49
  • @Kayla It means the value being shifted must be the correct type. The constant `1` has type `int`, so shifting left by more than 31 triggers undefined behavior. The `ULL` suffix gives it type `unsigned long long` which it at least 64 bits. – dbush Jun 07 '22 at 01:51