Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C bit-wise operations with hex numbers

Tags:

c

hex

Is there a way to access certain parts of a hexadecimal number in C?

I want to write a function that takes in a hexadecimal number and negates it, but leaves the least significant byte unchanged. Example: 0x87654321 should become 0x789ABC21.

I've tried to somehow save the LSB and then apply it to the negated x, but my problem is that my mask gets applied to all bytes. I could hard code it for a specific value, but obviously that's not what I want.

void b(int x) {
  int temp = x & 0xFF; // temp is all 0 with the LSB being the same as x's
  x = ~x;  // this negates x
  // one of a couple of attempts I tried thus far:
  // x = (x & 0x00) | temp; 
  // idea: change x's LSB to 00 and OR it with temp, 
  // changing x's LSB to temp's LSB
}

I'd appreciate if you don't post code for the solution, but rather just answer whether there is a way to apply bit operations to specific sections of a hexadecimal number, or how I could possibly solve this.

like image 791
Beko Avatar asked Feb 12 '23 01:02

Beko


1 Answers

In general you can operate on specific bits of a value by using a mask.

A mask is bit-pattern with 1s where you want to operate and 0s where you don't.

It seems like you need 3 operations: extract lowest byte, negate, restore lowest byte. You can figure out negation, so I'll just talk about extracting a bit-field and restoring an extracted bit-field.

To extract specified bits, use a mask with 1s for the desired bits and use the bitwise and operator &. The and operator sets 0s for all 0s of the mask, and where the mask is 1, it copies the bits from the other argument. If you need to examine this value elsewhere in your program, it may also be convenient to right-shift >> the value down to the lowest position (so it's easier to lookup in tables).

To restore saved bits, shift back up if you shifted it down earlier. Then clear those bits from the value, and use inclusive-or | as a bitwise sum of all one bits. To clear the bits from the value, use the inverse of the mask from the first operation. Ie. y = x & 0xf saves a nibble, x & ~0xf clears that nibble, (x & ~0xf) | y recombines to the same original x.

Edit: If the piece you're extracting is not in the lowest position, say the second byte (LSB) from a 32 bit unsigned integer, then it may be useful to shift the extracted value to the zero position to work with it.

x = 0x12345678;
y = x & 0xFF00;  // == 0x5600
y >>= 8;         // == 0x56

But if you do this then you have to shift it back to the correct position (of course) before updating the larger value with a new value for the bitfield.

x = (x & ~0xFF00) | (y << 8);
like image 144
luser droog Avatar answered Feb 13 '23 20:02

luser droog