constructing 32 bit unsigned int in c - c

I am trying to construct a 32 bit binary value using an unsigned int. This is how
the 32 bit is split into parts
part 1 = 4 bit
part 2 = 2 bit
part 3 = 12 bit
part 4 = 2 bit
part 5 = 12 bit
How do i use the parts to construct 32 bit binary value (unsigned int) using
bit shifting can someone please help
(cant just shift bits... what if i want to update certain part?)

This is typical bit-shifting/bit-masking stuff. Here's how you set the initial value:
uint32_t value = ((part1 & 0xF) << 28)
| ((part2 & 0x3) << 26)
| ((part3 & 0xFFF) << 14)
| ((part4 & 0x3) << 12)
| (part5 & 0xFFF);
Each line uses a bitwise-AND (&) to clear the upper bits of each part so it doesn't overflow its allocated bit-width within the final value. For example, if part4 was 0xFF and you forgot the & 0x3 then the upper 6 bits of part4 (0xFC) would spill into the region for part3. Then the part is shifted (<<) to its final location and bitwise-OR'd (|) with the rest of the parts.
Some developers accomplish the same thing via bitfields but I don't recommend that approach due to potential portability issues.
Most (all?) of the other answers here so far have forgotten the bitwise-AND portion of the solution. Their answers will result in bugs if the part values ever exceed the specified bit width.
If you want to update a particular portion of the value, you'll need some more bit-masking via bitwise-AND and bitwise-OR. For example, to update part4 you'd do this:
value &= ~(0x3 << 12); /* Clear the part4 region */
value |= (part4 & 0x3) << 12; /* Set the part4 region to the new value */
That first line is a little tricky if you're new to bitwork in C. It says take 0x3 and shift it by 12 (result = 0x00003000), perform a bitwise-complement (result = 0xFFFFCFFF), and set value equal to itself bitwise-AND'd with that result. That's how you clear the part4 region of the value... because you're bitwise-AND'ing that region with zero the result is that region is now zero.
The second line sets the zeroed part4 region to the new value, just like we did above when setting the initial value.

You just use shifting, as you suggested:
uint32_t x = (part1 << 28)
| (part2 << 26)
| (part3 << 14)
| (part4 << 12)
| (part5);

Looks like you want this value:
part5 + (part4 << 12) + (part3 << 14) + (part2 << 26) + (part1 << 28)
(Make sure all five variables are of type uint32_t or some such.)

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

How to make a word from Byte []?

I am new to programming world, I want to convert two bytes into a word.
So basically, I have a Byte array where index 0 is Buffer[0]=08 and index 1 is Buffer[1]=06
I want to create a word from these two bytes
where word ETHType to be 0x0806
You would use bitwise operators and bit shifting.
uint16_t result = ((uint16_t)Buffer[0] << 8) | Buffer[1];
This does the following:
The value of Buffer[0] is shifted 8 bits to the left. That gives you 0x0800
A bitwise OR is performed between the prior value and the value of Buffer[1]. This sets the low order 8 bits to Buffer[1], giving you 0x0806
word ETHType = 0;
ETHType = (Buffer[0] << 8) | Buffer[1];
edit: You should probably add a mask to each operation to make sure there is no bit overlap, and you can do it safely in one line.
word ETHType = (unsigned short)(((unsigned char)(Buffer[0] & 0xFF) << 8) | (unsigned char)(Buffer[1] & 0xFF)) & 0xFFFF;
Here's a macro I use for this very thing:
#include <stdint.h>
#define MAKE16(a8, b8) ((uint16_t)(((uint8_t)(((uint32_t)(a8)) & 0xff)) | ((uint16_t)((uint8_t)(((uint32_t)(b8)) & 0xff))) << 8))

Bit Masking in a Cache

In C I am attempting to separate an integer address value into the tag bit and the set index bit in a direct mapped cache with 4 sets. I do this so I can compare the correct tags at the line in the correct set of my cache. Here for example the address parameters:
number of set index bits s=2
number of offset bits b=3
total number of address bits m=8
And in my example the address integer is 40 -- int address = 40.
40 in binary is 00101000
The set index should be 01 = 1
The tag should be 001 = 1
Instead for the tag I am getting 2 and the set index is 8 which have to be wrong because I only have 4 sets in my cache.
Here is how I am doing it, I am bit-masking the address to get the tag, which are the bits to the left of the set index up to the m=8 bit. And the set index is between the tag and offset bits which is the 01 in the middle of the 8 bit sequence.
int tag = ((address & ~0 << (s + b)) >> 4)
int set = (address & (~(~0 << s) << b))
I know I must be wrong but the more I try to write a mask the more I am getting confused and I must be forgetting something. I at least thought I was getting the tag right because the left bits should be easier than getting middle bits. Any advice or help would be greatly appreciated thanks a lot!
These equations will work for you:
tag = (address >> 5) & 0x7;
set = (address >> 3) & 0x3;
If you want to use the variables s, b, and m:
tag = (address >> (m-b)) & ((1u << b)-1);
set = (address >> (m-b-s)) & ((1u << s)-1);
In general if you want to extract N bits starting at bit i:
bits = (value >> i) & ((1u << N)-1);

Casting 8-bit int to 32-bit

I think I confused myself with endianness and bit-shifting, please help.
I have 4 8-bit ints which I want to convert to a 32-bit int. This is what I an doing:
uint h;
t_uint8 ff[4] = {1,2,3,4};
if (BIG_ENDIAN) {
h = ((int)ff[0] << 24) | ((int)ff[1] << 16) | ((int)ff[2] << 8) | ((int)ff[3]);
}
else {
h = ((int)ff[0] >> 24) | ((int)ff[1] >> 16) | ((int)ff[2] >> 8) | ((int)ff[3]);
}
However, this seems to produce a wrong result. With a little experimentation I realised that it should be other way round: in the case of big endian I am supposed to shift bits to the right, and otherwise to the left. However, I don't understand WHY.
This is how I understand it. Big endian means most significant byte first (first means leftmost, right? perhaps this where I am wrong). So, converting 8-bit int to 32-bit int would prepend 24 zeros to my existing 8 bits. So, to make it a 1st byte I need to shift bits 24 to the left.
Please point out where I am wrong.
You always have to shift the 8-bit-values left. But in the little-endian case, you have to change the order of indices, so that the fourth byte goes into the most-significant position, and the first byte into the least-significant.
if (BIG_ENDIAN) {
h = ((int)ff[0] << 24) | ((int)ff[1] << 16) | ((int)ff[2] << 8) | ((int)ff[3]);
}
else {
h = ((int)ff[3] << 24) | ((int)ff[2] << 16) | ((int)ff[1] << 8) | ((int)ff[0]);
}

Bitwise OR of constants

While reading some documentation here, I came across this:
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
I have no idea how this works. I read up on the bitwise operators in C, but I do not understand how you can fit three (or more!) constants inside one int and later being able to somehow extract them back from the int? Digging further down the documentation, I also found this, which is probably related:
typedef enum {
kCFCalendarUnitEra = (1 << 1),
kCFCalendarUnitYear = (1 << 2),
kCFCalendarUnitMonth = (1 << 3),
kCFCalendarUnitDay = (1 << 4),
kCFCalendarUnitHour = (1 << 5),
kCFCalendarUnitMinute = (1 << 6),
kCFCalendarUnitSecond = (1 << 7),
kCFCalendarUnitWeek = (1 << 8),
kCFCalendarUnitWeekday = (1 << 9),
kCFCalendarUnitWeekdayOrdinal = (1 << 10),
} CFCalendarUnit;
How do the (1 << 3) statements / variables work? I'm sorry if this is trivial, but could someone please enlighten me by either explaining or maybe posting a link to a good explanation?
Basically, the constants are represented just by one bit, so if you have a 32 bit integer, you can fit 32 constants in it. Your constants have to be powers of two, so they take only one "set" bit to represent.
For example:
#define CONSTANT_1 0x01 // 0001 in binary
#define CONSTANT_2 0x02 // 0010 in binary
#define CONSTANT_3 0x04 // 0100 in binary
then you can do
int options = CONSTANT_1 | CONSTANT_3; // will have 0101 in binary.
As you can see, each bit represents that particular constant. So you can binary AND in your code and test for the presence of each constant, like:
if (options & CONSTANT_3)
{
// CONSTANT_3 is set
}
I recommend you to read about binary operations (they work like LOGICAL operators, but at the bit level), if you grok this stuff, it will make you a bit better of a programmer.
Cheers.
If you look at a number in binary, each digit is either on (1) or off (0).
You can use bitwise operators to set or interrogate the individual bits efficiently to see if they are set or not.
Take the 8 bit value 156. In binary this is 10011100.
The set bits correspond to bits 7,4,3, and 2 (values 128, 16, 8, 4). You can compute these values with 1 << (position) rather easily. So, 1 << 7 = 128.
The number 1 is represented as 00000000000000000000000000000001
(1 << n) means shift the 1 in 1's representation n places to the left
So (1 << 3) would be 00000000000000000000000000001000
In one int you can have 32 options each of which can be turned on or off.
Option number n is on if the n'th bit is 1
1 << y is basically the same thing as 2 to the power of y
More generally, x << y is the same thing as x multiplied by 2 to the power of y.
In binary x << y means moving all the bits of x to the left by y places, adding zeroes in the place of the moved bits:
00010 << 2 = 01000
So:
1 << 1 = 2
1 << 2 = 4
1 << 3 = 8
...
<< is the shift left operator, it shifts the bits of the first operand left by the number of positions specified in the right operand (with zeros coming into the shifted positions from the right).
In your enum you end up with values that eacg have a different bit set to 1, so when you construct something like unitDate, you can later find out which flags it contains by using the & operator, e.g. unitDate & NSMonthCalendarUnit == NSMonthCalendarUnit will be true.

Resources