C bit-wise operations with hex numbers - c

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.

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);

If I correctly understood the question, seems like it would be something like this (untested).
void b(int x) {
return (~x & ~0xFF) | (x & 0xFF);
}

I've found a way to manipulate a chosen byte. (!!! This would be homework 2.60 of CS:APP !!!)
If 0x12345678 is a given hexadecimal value of type, say int, then doing this will allow me to change the ith byte:
int x = 0x12345678;
unsigned char* xptr = (unsigned char*) &x;
xptr[i] = 0; // say i=2, then this would yield: 0x120045678
Now, if I want to add a value in the position of byte i, say 0xAB, I'd do what luser droog already mentioned:
int temp = 0xAB;
temp = temp << i*8; // say i=2, then this would yield: 0x00AB0000
x = x | temp; // this yields the desired result 0x12AB3456

Related

How can I split one long value which was 'build' from 2 int-values back into its 2 integers?

I have (not mine) a program that reads long values from a data-file.
I can change the numbers in the data-file and I can do s.th. with the number the program has read from the data-file.
Now I want to write 2 integer-values (2*4 byte) in the data-file instead of one (small) long-value (8 byte).
What do I have to do with the number I get in the program to 'split' that into the two initial integer-values?
What I read is s.th. like 54257654438765. How do I split that?
That program offers me some (c-like) bitwise operations:
x = x << y; // left shift
x = x >> y; // right shift
b = ((x & y) != 0); // Bitwise AND
b = ((x | y) != 0); // Bitwise OR
b = x ^ y; // Bitwise Exclusive Operation OR
But these operators are working in that program only with integer- not long-values and I assume that 2 integers together get bigger than the highest possible integer +-2'147'483'647).
Is there a numeric approach (from the value I see) to get back the two int-values?
I have never tried that and I appreciate any hint!
That is a easy one. You got your 64-bit value. The upper 32-bit is one value, the lower another.
The trick is to get the values into position to a cast to a 32-bit integer works. So casting your 64-bit value to a integer and storing it in a integer variable, will give you the lower 32-bit value right away.
For the upper value you need to do some shifting. You need to move the upper values by 32bit to the right to get them into position.
So basically:
uint64 longValue = /* Your long value. */;
uint32 firstIntValue = (uint32) longValue;
uint32 secondIntValue = (uint32) (longValue >> 32);
As the cast will discard all bits not fitting into the new variable that should work just fine.
EDIT:
And as requested by comment. Also the other way round:
uint64 longValue = secondIntValue;
longValue = longValue << 32; /* If its C: longValue <<= 32; */
longValue = longValue | firstIntValue; /* If its C: longValue |= firstIntValue; */
The idea here is to first put the the integer that is supposed to end up in the higher bits to the 64-bit storage and move them with the shift to the up bits. After that place the lower value with a OR operation in the lower bits. You can't perform a simple assignment in the last operation because that would kill the upper bits.
Just as additional information. You can get around all that shifting entirely in case you are able to use unions and structs in the language you are using. If its plain C that is possible.

Invert specific bits using bitwise NOT (no XOR)

How can I use Bitwise Not to invert specific bits for x number? I know we can do this use XOR and mask but question requires use NOT.
I need to invert a group of bits starting at a given position. The variable inside the function includes original value, position wants to start and width = number of bits I want to invert.
I use the shift bit to start from a given position but how can I ensure only x number of bits are inverted using NOT Bitwise function?
Definition of xor: a ^ b <--> (a & ~b) | (~a & b)
unsigned x = 0x0F;
unsigned mask = 0x44; // Selected bits to invert
unsigned selected_x_bits_inverted = (x & ~mask) | (~x & mask);
printf("%02X\n", selected_x_bits_inverted);
// 4B
An approach would be:
First, extract them into y:
y = x & mask
Then, invert y and get only the bits you need:
y = ~y & mask
Clear the bits extracted from x:
x = x & (~mask)
OR those 2 numbers to get the result:
x = x | y
Note that every bit that has to be inverted is 1 in mask. Even if I used other bitwise operators, the actual bit flipping is done by a bitwise not. Also, I don't think it is possible to achieve this result without using some other binary operators.
This function will invert 'width' number of bits of number 'num' from position 'pos'
int invert(int num, int pos, int width)
{
int mask = (~((~0) << width)) << pos;
num = (~(num & mask)) & mask);
}

C expression that sets the last n bits of int variable to zero

In other words, sets the last 5 bits of integer variable x to zero, also it must be in a portable form.
I was trying to do it with the << operator but that only moves the bits to the left, rather than changing the last 5 bits to zero.
11001011 should be changed to 11000000
Create a mask that blanks out that last n integers if it is bitwise-ANDed with your int:
x &= ~ ((1 << n) - 1);
The expression 1 << n shifts 1 by n places and is effectively two to the power of n. So for 5, you get 32 or 0x00000020. Subtract one and you get a number that as the n lowest bits set, in your case 0x0000001F. Negate the bits with ~ and you get 0xFFFFFFE0, the mask others have posted, too. A bitwise AND with your integer will keep only the bits that the mask and your number have in common, which can only bet bits from the sixth bit on.
For 32-bit integers, you should be able to mask off those bits using the & (bitwise and) operator.
x & 0xFFFFFFE0.
http://en.wikipedia.org/wiki/Bitwise_operation#AND
You can use bitwise and & for this
int x = 0x00cb;
x = x & 0xffe0;
This keeps the higher bits and sets the lower bits to zero.

How to flip a specific bit in a byte in C?

I'm trying to use masks and manipulating specific bits in a byte.
For example:
I want to write a program in C that flips two bits at particular positions e.g. the bit at position 0 and the one at the third position.
So, 11100011, would become 01110011.
How can I swap these bits?
Flipping a bit is done by XOR-ing with a mask: set bits at the positions that you want to flip, and then execute a XOR, like this:
int mask = 0x90; // 10010000
int num = 0xE3; // 11100011
num ^= mask; // 01110011
Here are a few notes:
bits are commonly counted from the least significant position, so your example flips bits in positions 4 and 7, not at positions 0 and 4
To construct a bit mask for a single position, use expression 1 << n, where n is the position number counting from the least significant bit.
To combine multiple bits in a single mask, use | operator. For example, (1 << 4) | (1 << 7) constructs the mask for flipping bits 4 and 7.
If your byte is x, and you want to switch the bits at the i-th and j-th position:
x = x ^ ((1<<i) | (1<<j));
So, in your case, it would just be (1<<4) | (1<<7). :)
First of all, good luck!
One remark - it is more useful to count the bits from the right and not left, since there are various byte/word sizes (8-bit,16-bit,etc.) and that count preserves compatibility better. So in your case you are referring to bits #7 and #4 (zero-count).
Did you mean 'flip' (change 0<->1 bits) or 'switch' them between one and the other?
For the first option, the answer above (XOR with "int mask = 0x90; // 10010000") is very good. For the second one, it's a bit more tricky (but not much).
To flip bits, you can use the exclusive OR bitwise operator. This takes two operands (typically, the value you want to operate on and the mask defining what bits will be flipped). The eXclusive OR (XOR) operator will only flip a bit if, and only if, one of the two is set to 1, but NOT both. See the (simple) example below:
#include <stdio.h>
int main(int argc, char** argv)
{
int num = 7; //00000111
int mask = 3; //00000011
int result = num ^ mask; //00000100
printf("result = %d\n", result); //should be 4
return 0;
}

How to create mask with least significat bits set to 1 in C

Can someone please explain this function to me?
A mask with the least significant n bits set to 1.
Ex:
n = 6 --> 0x2F, n = 17 --> 0x1FFFF // I don't get these at all, especially how n = 6 --> 0x2F
Also, what is a mask?
The usual way is to take a 1, and shift it left n bits. That will give you something like: 00100000. Then subtract one from that, which will clear the bit that's set, and set all the less significant bits, so in this case we'd get: 00011111.
A mask is normally used with bitwise operations, especially and. You'd use the mask above to get the 5 least significant bits by themselves, isolated from anything else that might be present. This is especially common when dealing with hardware that will often have a single hardware register containing bits representing a number of entirely separate, unrelated quantities and/or flags.
A mask is a common term for an integer value that is bit-wise ANDed, ORed, XORed, etc with another integer value.
For example, if you want to extract the 8 least significant digits of an int variable, you do variable & 0xFF. 0xFF is a mask.
Likewise if you want to set bits 0 and 8, you do variable | 0x101, where 0x101 is a mask.
Or if you want to invert the same bits, you do variable ^ 0x101, where 0x101 is a mask.
To generate a mask for your case you should exploit the simple mathematical fact that if you add 1 to your mask (the mask having all its least significant bits set to 1 and the rest to 0), you get a value that is a power of 2.
So, if you generate the closest power of 2, then you can subtract 1 from it to get the mask.
Positive powers of 2 are easily generated with the left shift << operator in C.
Hence, 1 << n yields 2n. In binary it's 10...0 with n 0s.
(1 << n) - 1 will produce a mask with n lowest bits set to 1.
Now, you need to watch out for overflows in left shifts. In C (and in C++) you can't legally shift a variable left by as many bit positions as the variable has, so if ints are 32-bit, 1<<32 results in undefined behavior. Signed integer overflows should also be avoided, so you should use unsigned values, e.g. 1u << 31.
For both correctness and performance, the best way to accomplish this has changed since this question was asked back in 2012 due to the advent of BMI instructions in modern x86 processors, specifically BLSMSK.
Here's a good way of approaching this problem, while retaining backwards compatibility with older processors.
This method is correct, whereas the current top answers produce undefined behavior in edge cases.
Clang and GCC, when allowed to optimize using BMI instructions, will condense gen_mask() to just two ops. With supporting hardware, be sure to add compiler flags for BMI instructions:
-mbmi -mbmi2
#include <inttypes.h>
#include <stdio.h>
uint64_t gen_mask(const uint_fast8_t msb) {
const uint64_t src = (uint64_t)1 << msb;
return (src - 1) ^ src;
}
int main() {
uint_fast8_t msb;
for (msb = 0; msb < 64; ++msb) {
printf("%016" PRIx64 "\n", gen_mask(msb));
}
return 0;
}
First, for those who only want the code to create the mask:
uint64_t bits = 6;
uint64_t mask = ((uint64_t)1 << bits) - 1;
# Results in 0b111111 (or 0x03F)
Thanks to #Benni who asked about using bits = 64. If you need the code to support this value as well, you can use:
uint64_t bits = 6;
uint64_t mask = (bits < 64)
? ((uint64_t)1 << bits) - 1
: (uint64_t)0 - 1
For those who want to know what a mask is:
A mask is usually a name for value that we use to manipulate other values using bitwise operations such as AND, OR, XOR, etc.
Short masks are usually represented in binary, where we can explicitly see all the bits that are set to 1.
Longer masks are usually represented in hexadecimal, that is really easy to read once you get a hold of it.
You can read more about bitwise operations in C here.
I believe your first example should be 0x3f.
0x3f is hexadecimal notation for the number 63 which is 111111 in binary, so that last 6 bits (the least significant 6 bits) are set to 1.
The following little C program will calculate the correct mask:
#include <stdarg.h>
#include <stdio.h>
int mask_for_n_bits(int n)
{
int mask = 0;
for (int i = 0; i < n; ++i)
mask |= 1 << i;
return mask;
}
int main (int argc, char const *argv[])
{
printf("6: 0x%x\n17: 0x%x\n", mask_for_n_bits(6), mask_for_n_bits(17));
return 0;
}
0x2F is 0010 1111 in binary - this should be 0x3f, which is 0011 1111 in binary and which has the 6 least-significant bits set.
Similarly, 0x1FFFF is 0001 1111 1111 1111 1111 in binary, which has the 17 least-significant bits set.
A "mask" is a value that is intended to be combined with another value using a bitwise operator like &, | or ^ to individually set, unset, flip or leave unchanged the bits in that other value.
For example, if you combine the mask 0x2F with some value n using the & operator, the result will have zeroes in all but the 6 least significant bits, and those 6 bits will be copied unchanged from the value n.
In the case of an & mask, a binary 0 in the mask means "unconditionally set the result bit to 0" and a 1 means "set the result bit to the input value bit". For an | mask, an 0 in the mask sets the result bit to the input bit and a 1 unconditionally sets the result bit to 1, and for an ^ mask, an 0 sets the result bit to the input bit and a 1 sets the result bit to the complement of the input bit.

Resources