Modify higher bits of a variable in C - c

I have a variable in C with a binary value of '10010100'
and I have another variable with the value is '1111'.
What I want to achieve is to keep bits 7,6,1,0 intact and insert the second variable in [5..2].
I have been told I could use a mirror. I have done some research and I cannot find the right answer.
If I move bits bitwise, I lose part of the content.

Use a mask (bitwise AND) to turn the part that should be replaced to the new values to zero.
Use bitwise OR to put the new value to the zeroed area.
int a = 0x94; /* 10010100 */
int b = 0xf; /* 1111 */
/* do masking here */
/* | put the new value here */
/* | | */
/* v v */
a = (a & ~(0xf << 2)) | (b << 2);

The general solution to this problem is to clear the bits in the destination range with the & operator and an appropriate mask and set the bits from the second variable, shifted appropriately and potentially masked if it cannot be asserted that no other bits are set:
v1 = (v1 & ~(0xF << 2)) | ((v2 & 0xF) << 2);
If you know that v2 has all bits set in the destination range, you can simplify as:
v1 = v1 | (0xF << 2);
Note however that (v1 & ~(0xF << 2)) uses int arithmetics, which will extend the mask to the width of v1 if its type is larger than int. But if the destination included the sign bit of type int, shifting a 1 bit into this position is undefined behavior. Using an explicit constant would not work either because it would have type unsigned int and extending it to the type of v1 would also mask the high order bits of v1 if its type is larger than int. For example:
/* replacing bits 31,30,29,28 */
long long v1 = 0x987654321;
int v2 = 0xF;
v1 = (v1 & ~(0xF << 28)) | ((v2 & 0xF) << 28);
// v1 is now 0x9F7654321 but really undefined behavior
v1 = (v1 & ~0xF0000000) | ((v2 & 0xF) << 28);
// v1 is now 0xF7654321 instead of 0x9F7654321
A similar issue occurs if v2 has a type smaller than that of v1 and must be shifted beyond its own length.
A safer approach would use constants with trailing type markers that match the type of v1, but this would still not work if a bit has to be shifted into the sign bit of type long long:
v1 = (v1 & ~(0xFLL << 60)) | ((v2 & 0xFLL) << 60); // undefined behavior
The general solution is to use unsigned long long constants:
v1 = (v1 & ~(0xFULL << 28)) | ((v2 & 0xFULL) << 28);
The behavior on obsolete non 2's complement architectures is non trivial and will be ignored.

Here is how I would break it down into small pieces.
Note that the 0b prefix is a non-standard extension, but commonly found on several compilers.
#include <stdio.h>
#include <stdint.h>
int main(void) {
uint8_t a = 0b10010100;
uint8_t b = 0b00001111;
uint8_t keep7610 = a & 0b11000011; // Keep Bits 7, 6, 1, and 0. Set the others to 0
uint8_t insertb = keep7610 | (b << 2); // Add in variable B at position 2-5
printf("Final Answer: 0x%02X\n", insertb);
return 0;
}
Output
Success #stdin #stdout 0s 5444KB
Final Answer: 0xBC
(0xBC translates as 0b10111100, which is what I get when I follow your instructions manually)

Use functions!
unsigned replaceBits(unsigned val, int startBit, int nBits, unsigned newVal)
{
unsigned mask = ((1UL << nBits) - 1) << startBit;
//clear bits
val &= ~mask;
//set new value (adding with mask makes sure that we will not change any other bits.
val |= (newVal << startBit) & mask;
return val;
}
You can also add some checks to make sure that parameters have valid values.
Example:
https://godbolt.org/z/zofKqofx1

Related

C set 3 bits for a particular number

I am trying to understand masking concept and want to set bits 24,25,26 of a uint32_t number in C.
example i have
uint32_t data =0;
I am taking an input from user of uint_8 which can be only be value 3 and 4 (011,100)
I want to set the value 011 or 110 in bits 24,25,26 of the data variable without disturbing other bits.
Thanks.
To set bits 24, 25, and 26 of an integer without modifying the other bits, you can use this pattern:
data = (data & ~((uint32_t)7 << 24)) | ((uint32_t)(newBitValues & 7) << 24);
The first & operation clears those three bits. Then we use another & operation to ensure we have a number between 0 and 7. Then we shift it to the left by 24 bits and use | to put those bits into the final result.
I have some uint32_t casts just to ensure that this code works properly on systems where int has fewer than 32 bits, but you probably won't need those unless you are programming embedded systems.
More general approach macro and function. Both are the same efficient as optimizing compilers do a really good job. Macro sets n bits of the d at position s to nd. Function has the same parameters order.
#define MASK(n) ((1ULL << n) - 1)
#define SMASK(n,s) (~(MASK(n) << s))
#define NEWDATA(d,n,s) (((d) & MASK(n)) << s)
#define SETBITS(d,nd,n,s) (((d) & SMASK(n,s)) | NEWDATA(nd,n,s))
uint32_t setBits(uint32_t data, uint32_t newBitValues, unsigned nbits, unsigned startbit)
{
uint32_t mask = (1UL << nbits) - 1;
uint32_t smask = ~(mask << startbit);
data = (data & smask) | ((newBitValues & mask) << startbit);
return data;
}

Working with bits-output in c

I have to say what the output of the program for w = 33. I do not know how to do it. Does anyone have an idea how to solve this without writing the binary representation of each number?
void notChicken(int w)
{
unsigned int v1 = 0x12345678;
unsigned int v2 = 0x87654785;
unsigned int v3 = 0xffffffff;
unsigned int tmp;
tmp = (v1 >> 3) | (v2 << 3);
tmp &= v3 & ~(v3 << (w >> 1));
printf("%8x\n", tmp);
}
Thanks
Although not a good idea, lets try to break down your operation.
You have given w = 33
The last part -
v3 & ~(v3 << (w >> 1)) is going to evaluate as v3 & ~(v3 << 16)
v3 << 16 is 0xffff0000 and ~ of that is 0xffff
since v3 is all ones you get 0xffff. This will mask off the upper 16 bits of the previous computation.
Now (v1 >> 3) | (v2 << 3);
We care only about the lower 16 bits.
>> 3 is dividing by 8 and << 3 is multiplying by 8.
So the result of first part will be
0x2468ACF | 0x3B2A3C28
Keeping only the lower 16 bits
0x8ACF | 0x3C28
Finally I don't know how you are going to do the OR without writing the bitwise representation. I can help with the last hex. It will be F.

Bit wise operators

am having a little trouble with this function of mine. We are supposed to use bit wise operators only (that means no logical operators and no loops or if statements) and we aren't allowed to use a constant bigger than 0xFF.
I got my function to work, but it uses a huge constant. When I try to implement it with smaller numbers and shifting, I can't get it to work and I'm not sure why.
The function is supposed to check all of the even bits in a given integer, and return 1 if they are all set to 1.
Working code
int allEvenBits(int x) {
/* implements a check for all even-numbered bits in the word set to 1 */
/* if yes, the program outputs 1 WORKING */
int all_even_bits = 0x55555555;
return (!((x & all_even_bits) ^ all_even_bits));
}
Trying to implement with a smaller constant and shifts
int allEvenBits(int x) {
/* implements a check for all even-numbered bits in the word set to 1 */
/* if yes, the program outputs 1 WORKING */
int a, b, c, d, e = 0;
int mask = 0x55;
/* first 8 bits */
a = (x & mask)&1;
/* second eight bits */
b = ((x>>8) & mask)&1;
/* third eight bits */
c = ((x>>16) & mask)&1;
/* fourth eight bits */
d = ((x>>24) & mask)&1;
e = a & b & c & d;
return e;
}
What am I doing wrong here?
When you do, for example, this:
d = ((x>>24) & mask)&1;
..you're actually checking whether the lowest bit (with value 1) is set, not whether any of the the mask bits are set... since the &1 at the end bitwise ANDs the result of the rest with 1. If you change the &1 to == mask, you'll instead get 1 when all of the bits set in mask are set in (x>>24), as intended. And of course, the same problem exists for the other similar lines as well.
If you can't use comparisons like == or != either, then you'll need to shift all the interesting bits into the same position, then AND them together and with a mask to eliminate the other bit positions. In two steps, this could be:
/* get bits that are set in every byte of x */
x = (x >> 24) & (x >> 16) & (x >> 8) & x;
/* 1 if all of bits 0, 2, 4 and 6 are set */
return (x >> 6) & (x >> 4) & (x >> 2) & x & 1;
I don't know why you are ANDing your values with 1. What is the purpose of that?
This code is untested, but I would do something along the lines of the following.
int allEvenBits(int x) {
return (x & 0x55 == 0x55) &&
((x >> 8) & 0x55 == 0x55) &&
((x >> 16) & 0x55 == 0x55) &&
((x >> 24) & 0x55 == 0x55);
}
Say you are checking the first 4 least significant digits, the even ones would make 1010. Now you should AND this with the first 4 bits of the number you're checking against. All 1's should remain there. So the test would be ((number & mask) == mask) (mask is 1010) for the 4 least significant bits, you do this in blocks of 4bits (or you can use 8 since you are allowed).
If you aren't allowed to use constants larger than 0xff and your existing program works, how about replacing:
int all_even_bits = 0x55555555;
by:
int all_even_bits = 0x55;
all_even_bits |= all_even_bits << 8; /* it's now 0x5555 */
all_even_bits |= all_even_bits << 16; /* it's now 0x55555555 */
Some of the other answers here right shift signed integers (i.e. int) which is undefined behaviour.
An alternative route is:
int allevenbitsone(unsigned int a)
{
a &= a>>16; /* superimpose top 16 bits on bottom */
a &= a>>8; /* superimpose top 8 bits on bottom */
a &= a>>4; /* superimpose top 4 bits on bottom */
a &= a>>2; /* and down to last 2 bits */
return a&1; /* return & of even bits */
}
What this is doing is and-ing together the even 16 bits into bit 0, and the odd 16 bits into bit 1, then returning bit 0.
the main problem in your code that you're doing &1, so you take first 8 bits from number, mask them with 0x55 and them use only 1st bit, which is wrong
consider straightforward approach:
int evenBitsIn8BitNumber(int a) {
return (a & (a>>2) & (a>>4) & (a>>6)) & 1;
}
int allEvenBits(int a) {
return evenBitsIn8BitNumber(a) &
evenBitsIn8BitNumber(a>>8) &
evenBitsIn8BitNumber(a>>16) &
evenBitsIn8BitNumber(a>>24);
}

Changing endianness on 3 byte integer

I am receiving a 3-byte integer, which I'm storing in an array. For now, assume the array is unsigned char myarray[3]
Normally, I would convert this into a standard int using:
int mynum = ((myarray[2] << 16) | (myarray[1] << 8) | (myarray[0]));
However, before I can do this, I need to convert the data from network to host byte ordering.
So, I change the above to (it comes in 0-1-2, but it's n to h, so 0-2-1 is what I want):
int mynum = ((myarray[1] << 16) | (myarray[2] << 8) | (myarray[0]));
However, this does not seem to work. For the life of me can't figure this out. I've looked at it so much that at this point I think I'm fried and just confusing myself. Is what I am doing correct? Is there a better way? Would the following work?
int mynum = ((myarray[2] << 16) | (myarray[1] << 8) | (myarray[0]));
int correctnum = ntohl(mynum);
Here's an alternate idea. Why not just make it structured and make it explicit what you're doing. Some of the confusion you're having may be rooted in the "I'm storing in an array" premise. If instead, you defined
typedef struct {
u8 highByte;
u8 midByte;
u8 lowByte;
} ThreeByteInt;
To turn it into an int, you just do
u32 ThreeByteTo32(ThreeByteInt *bytes) {
return (bytes->highByte << 16) + (bytes->midByte << 8) + (bytes->lowByte);
}
if you receive the value in network ordering (that is big endian) you have this situation:
myarray[0] = most significant byte
myarray[1] = middle byte
myarray[2] = least significant byte
so this should work:
int result = (((int) myarray[0]) << 16) | (((int) myarray[1]) << 8) | ((int) myarray[2]);
Beside the ways of using strucures / unions with byte-size members you have two other ways
Using ntoh / hton and masking out the high byte of the 4-byte integer before or after
the conversion with an bitwise and.
Doing the bitshift operations contained in other answers
At any rate you should not rely on side effects and shift data beyond the size of data type.
Shift by 16 is beyond the size of unsigned char and will cause problems depending on compiler, flags, platform endianess and byte order. So always do the proper cast before bitwise to make it work on any compiler / platform:
int result = (((int) myarray[0]) << 16) | (((int) myarray[1]) << 8) | ((int) myarray[2]);
Why don't just receive into the top 3 bytes of a 4-byte buffer? After that you could use ntohl which is just a byte swap instruction in most architectures. In some optimization levels it'll be faster than simple bitshifts and or
union
{
int32_t val;
unsigned char myarray[4];
} data;
memcpy(&data, buffer, 3);
data.myarray[3] = 0;
data.val = ntohl(data.val);
or in case you have copied it to the bottom 3 bytes then another shift is enough
memcpy(&data.myarray[1], buffer, 3);
data.myarray[0] = 0;
data.val = ntohl(data.val) >> 8; // or data.val = ntohl(data.val << 8);
unsigned char myarray[3] = { 1, 2, 3 };
# if LITTLE_ENDIAN // you figure out a way to express this on your platform
int mynum = (myarray[0] << 0) | (myarray[1] << 8) | (myarray[2] << 16);
# else
int mynum = (myarray[0] << 16) | (myarray[1] << 8) | (myarray[2] << 0);
# endif
printf("%x\n", mynum);
That prints 30201 which I think is what you want. The key is to realize that you have to shift the bytes differently per-platform: you can't easily use ntohl() because you don't know where to put the extra zero byte.

Basic C Bitwise Operations Example

int sampleVariable; // declared and initialized and used elsewhere
if (sampleVariable & 2)
someCodeIwantExecuted();
So if i wanted to manually manipulate sampleVariable so that if statement to evaluate as true and someCodeIwantExecuted() to execute I would do the following ?
sampleVariable |= (1 << 1);
Keep in mind I don't know what the value of sampleVariable is and I want to keep the rest of the bits the same. Just change the bit so that if statement will always be true.
The solution is fairly direct.
// OP suggestion works OK
sampleVariable |= (1 << 1);
// #Adam Liss rightly suggests since OP uses 2 in test, use 2 here.
sampleVariable |= 2
// My recommendation: avoid naked Magic Numbers
#define ExecuteMask (2u)
sampleVariable |= ExecuteMask;
...
if (sampleVariable & ExecuteMask)
Note: when using the shift style as in (1 << 1), insure that the type of 1 matches your target type
unsigned long long x;
x |= 1 << 60; // May not work if `sizeof(int)` < `sizeof(x)`.
x |= 1ull << 60;
Further: Consider the advantages of unsigned types.
// Assume sizeof int/unsigned is 4.
int i;
y |= 1 << 31; // Not well defined
unsigned u;
u |= 1u << 31; // Well defined in C.

Resources