27

Say I have a byte like this 1010XXXX where the X values could be anything. I want to set the lower four bits to a specific pattern, say 1100, while leaving the upper four bits unaffected. How would I do this the fastest in C?

1

4 Answers 4

68

In general:

value = (value & ~mask) | (newvalue & mask); 

mask is a value with all bits to be changed (and only them) set to 1 - it would be 0xf in your case. newvalue is a value that contains the new state of those bits - all other bits are essentially ignored.

This will work for all types for which bitwise operators are supported.

Sign up to request clarification or add additional context in comments.

2 Comments

Can you please give a specific example? Suppose I have: n = 1024. I want to change bits from position 3 to 7 (inclusive, starting from 0 with the least significant bit) to k = 19. The result should be: 1176. How can I achieve it? Thank you.
Having just had to figure this out myself, I've come up with the following macros to generalise the problem. (No idea why code formatting isn't working, sorry) ``` #define MASK(L,P) (~(0xffffffff << (L)) << (P)) #define GET_VAL(BF,L,P) (((BF) & MASK(L,P)) >> P) #define SET_VAL(BF,L,P,V) ( (BF) = ((BF) & ~MASK(L,P)) | (((V) << (P)) & MASK(L,P)) ) int main(int argc, char ** argv) { uint32_t bf = 1024; printf("Bitfield before : %d , 0x%08x\n", bf, bf); SET_VAL(bf,5,3,19); printf("Bitfield after : %d , 0x%08x\n", bf, bf); return 0; } ```
22

You can set all those bits to 0 by bitwise-anding with the 4 bits set to 0 and all other set to 1 (This is the complement of the 4 bits set to 1). You can then bitwise-or in the bits as you would normally.

ie

 val &= ~0xf; // Clear lower 4 bits. Note: ~0xf == 0xfffffff0 val |= lower4Bits & 0xf; // Worth anding with the 4 bits set to 1 to make sure no // other bits are set. 

2 Comments

why ~0xf is equal to 0x0000000f (four bytes), why not 3 bytes or 5 bytes? Did the compiler decide the length 4 based on the sizeof val which to be ANDED with?
@doc_id: I am assuming that val is a 32-bit integer. It could be 16-bit or 64-bit but unlikely to be 24 or 40 bit as they are not standard integer types ...
3

To further generalise the answers given, here are a couple of macros (for 32-bit values; adjust for different bitfield lengths).

#include <stdio.h> #include <stdint.h> #define MASK(L,P) (~(0xffffffff << (L)) << (P)) #define GET_VAL(BF,L,P) (((BF) & MASK(L,P)) >> P) #define SET_VAL(BF,L,P,V) ( (BF) = ((BF) & ~MASK(L,P)) | (((V) << (P)) & MASK(L,P)) ) int main(int argc, char ** argv) { uint32_t bf = 1024; printf("Bitfield before : %d , 0x%08x\n", bf, bf); printf("Mask(5,3): %d , 0x%08x\n", MASK(5,3), MASK(5,3)); SET_VAL(bf,5,3,19); printf("Bitfield after : %d , 0x%08x\n", bf, bf); return 0; } 

As an aside, it's ridiculous that the C bitfield is completely useless. It's the perfect syntactic sugar for this requirement but due to leaving it up to each compiler to implement as it sees fit, it's useless for any real-world usage.

Comments

3

Use the bitwise OR operator, |, when you want to change the bit of a byte from 0 to 1.

Use the bitwise AND operator, &, when you want to change the bit of a byte from 1 to 0.

Example

#include <stdio.h> int byte; int chb; int main() { // Change bit 2 of byte from 0 to 1 byte = 0b10101010; chb = 0b00000100; // 0 to 1 change byte printf("%d\n", byte); // Display current status of byte byte = byte | chb; // Perform 0 to 1 single bit changing operation printf("%d\n", byte); // Change bit 2 of byte back from 1 to 0 chb = 0b11111011; // 1 to 0 change byte byte = byte & chb; // Perform 1 to 0 single bit changing operation printf("%d\n", byte); } 

Maybe there are better ways; I don’t know. This will help you for now.

1 Comment

Your program ultimately produces a value of byte that is the same value as the value you began with. May I ask, "What is the point of that?"

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.