Grabbing 'n' binary bits from end of unsigned int in C? Bit masking? - c

I'm pretty new to C and I seem to be messing up my bitmasking. From what I understand, it's a way to grab or create something of a subset from a binary value.
Say I want to grab the last 8 bits of an unsigned int value, containing 00001111000011110000111100001111.
How would I use AND/OR to grab those last 8?

Here's a more general solution to generate the mask based on how many bits you're interested int.
unsigned int last_n_bits(unsigned int value, int n)
{
unsigned int mask = -1;
if (n < sizeof(unsigned) * CHAR_BIT)
mask = ((1<<n)-1);
return value & mask;
}

You can use the BINARY AND operator for do a binary mask:
unsigned char last_eight_bits = my_number & 0b11111111

Mask-out all bits > 0xff:
value & 0xffu

Say I want to grab the last 8 bits of an unsigned int value, containing
00001111000011110000111100001111.
How would I use AND/OR to grab those last 8?
In this case, you would use AND. The following code will grab the 8 least significant bits:
unsigned int number = 0x0F0F0F0Fu;
unsigned int mask = 0x000000FFu; // set all bits to "1" which you want to grab
unsigned int result = number & mask; // result will be 0x0000000F
The &-Operator is used for an AND-Operation with each bit:
00001111000011110000111100001111
AND 00000000000000000000000011111111
------------------------------------
00000000000000000000000000001111
Be aware that "0 AND X = 0" and that "1 AND X = X". You can do further investigation at: https://en.wikipedia.org/wiki/Boolean_algebra.

Related

Test feedback: oddParitySet3 incorrectly returned

Purpose: Demonstrate the ability to manipulate bits using functions and to learn a little bit about parity bits.
Parity is a type of error detection where one of the bits in a bit string is used for this purpose. There are more complicated systems that can do more robust error detection as well as error correction. In this lab, we will use a simple version called odd parity. This reserves one bit as a parity bit. The other bits are examined, and the parity bit is set so that the number of 1 bits is odd. For example, if you have a 3-bit sequence, 110 and the rightmost bit is the parity bit, it would be set to 1 to make the number of 1s odd.
Notes: When referring to bit positions, bit 31 is the high-order bit (leftmost), and bit 0 is the low-order bit (rightmost). In order to work through these functions, you will likely have to map out bit patterns for testing to see how it all works. You may find using a converter that can convert between binary, hex, and decimal useful. Also, to assign bit patterns to integers, it might be easier to use hex notation. To assign a hex value in C, you can use the 0x????? where ????? are hex values. (There can be more or fewer than the number of ? here.) E.g.,
int i = 0x02A;
Would assign i = 42 in decimal.
Program Specifications: Write the functions below:
unsigned int leftRotate(unsigned int intArg, unsigned int rotAmt);
Returns an unsigned int that is intArg rotated left by rotAmt. Note: Rotate left is similar to shift left. The difference is that the bits shifted out at the left come back in on the right. Rotate is a common operation and often is a single machine instruction. Do not convert intArg to a string and operate on that. Do not use an array of ints (or other numbers). Use only integers or unsigned integers.
Example: Assuming you have 5-bit numbers, rotating the binary number 11000 left by 3 yields 00110
char *bitString(int intArg)
Returns a pointer to a character string containing the 32-bit pattern for the integer argument. The first character, index 0, should be the high-order bit and on down from there. For this function, you will need malloc. Can be used for printing bit patterns. E.g., if intArg = 24 the return string would be 00000000000000000000000000011000
unsigned int oddParitySet3(unsigned int intArg, unsigned int startBit);
This function will determine the odd parity for a 3-bit segment of intArg starting at bit startBit and set the parity bit (low-order bit) appropriately.
E.g., suppose intArg=3 and startBit = 2. The 32 bit representation, from high to low, would be 29 zeros then 110. So, bits 2 - 0 are 011. To make the parity odd, you would set bit zero to 0.
The return value is the modified intArg, in this case it would be 29 zeros then 010 or a value of 2.
Do not convert intArg to a string and operate on that. Use only integers or unsigned integers.
Note: If the start bit is greater than 31 or less than 2, this would present a problem (do you see this?). If this is the case, return a zero.
The compile command used by this zyLab is:
gcc main.c -Wall -Werror -Wextra -Wuninitialized -pedantic-errors -o a.out -lm
The program does not pass all tests and gives such errors:
enter image description here
C code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char * bitString(int intArg);
unsigned int leftRotate(unsigned int n, unsigned int d);
unsigned int oddParitySet3(unsigned int intArg, unsigned int startBit);
int main() {
return 0;
}
char * bitString(int intArg)
{
char *bits = (char*)malloc(33 * sizeof(char));
bits[32] = '\0';
for(int i = 31; i >= 0; i--)
{
if(intArg & (1 << i))
bits[31 - i] = '1';
else
bits[31 - i] = '0';
}
return bits;
}
unsigned int leftRotate(unsigned int intArg, unsigned int rotAmt)
{
return (intArg << rotAmt) | (intArg >> (32 - rotAmt));
}
unsigned int oddParitySet3(unsigned int intArg, unsigned int startBit){
unsigned int mask = 0x00000007;
unsigned int shiftedMask = mask << startBit;
unsigned int temp = intArg & shiftedMask;
unsigned int result = intArg;
if(__builtin_popcount(temp) % 2 == 0)
result |= shiftedMask;
else
result &= ~shiftedMask;
return result;
}
need help to fix the oddParitySet3 function so that it does not display errors that are in the photo.

Bit Operation in C

I am new in C and this is for a school project. I am implementing the Skinny Block Cipher in C.
My code:
unsigned char *bits[8]; // this array holds 1 byte of data.
... call in another func to convert hex to bit.
unsigned int four = bits[4] - '0'; // value 0
unsigned int seven = bits[7] - '0'; // value 1
unsigned int six = bits[6] - '0'; // value 1
four = four ^ ~(seven | six); // eq 1;
Now, my question
Do I have to convert the char to int every time to run the bit operation? What will happen if I do it using unsigned char?
If I store the value for eq - 1 on an unsigned int, the value is fe which is wrong (according to an online bit calculator), on the other hand, if I store the result in an unsigned char, the value is -2 which is correct. What's the difference? I am kind of lost here.
bits[8] is a pointer and I tried to do the eq 1 using indexes from bits pointer, like bits[4], etc but my VSCode throws an error and I don't understand why. Obviously, I have some gaps in my knowledge. I am using my Python knowledge to go through this.
I don't know if I am giving all the information that's needed. Hit me up for extras!
TIA.
I updated the code
unsigned char bits[9];
It converts a3 into 010100011.
unsigned char *bits[8]; // this array holds 1 byte of data.
No, it is an array of 8 pointers to char.
unsigned int four = bits[4] - '0'; // value 0
This will not work as you subtract the integer '0' from the pointer.
If you want to keep the string representation of the number in the binary form you need to define an array of 9 chars
char bits[9] = "10010110";
Then you can do the operations as in your code.
Do I have to convert the char to int every time to run the bit
operation? What will happen if I do it using unsigned char?
If you want to keep it as a string then - yes.
unsigned char x = 0x96;
unsigned int four = !!(x & (1 << 4));
unsigned int seven = !!(x & (1 << 7));
unsigned int six = !!(x & (1 << 6));

Is there a difference between a bit mask and a bit array?

I have heard the two terms used interchangeably. Is there a difference?
For example,
unsigned char chessboard : 64; /* Bit mask */
unsigned char chessboard_2 [64]; /* Bit array */
Bit Mask
A bit mask is a binary value that's used to refer to specific bits in an integer value when using bitwise operators. For instance, you might have:
unsigned int low3 = 0x7;
This is a bit mask with the low order 3 bits set. You can then use it to extract a part of a value:
unsigned int value = 030071;
unsigned int value_low3 = value & low3; // result is 01
or to update part of value:
unsigned int newvalue = (value & ~low3) | 5; // result is 030075
Bit Array
A bit array is an unsigned integer, or an array of unsigned integers, that's used to hold a sequence of boolean flags, where each value is in separate bits of the integer(s). If you have lots of boolean values to store, this is saves lots of memory compared to having each of them in a separate array element.
However, there's a tradeoff: in order to access a specific flag, you need to use masking and shifting.
If your bit array is small enough to fit in a single integer, you might declare:
uint32_t bitarray;
Then to access a specific element of it, you use:
bitvalue = (bitarray >> bitnum) & 0x1;
and to set an element:
bitarray |= (1u << bitnum);
and to clear an element:
bitarray &= ~(1u << bitnum);
If the bit array needs multiple words, you declare an array. You get the array index by dividing the bit number by the number of bits in each array element, then use the remainder to determine the bit number within that word and use the above expressions.
None of them is a bitmask. The first is the definition of a bitfield which should only be valid as a struct member and the second is an array of 64 unsigned chars.

Shifting bit values in C

Say I have the following code:
uint32_t fillThisNum(int16_t a, int16_t b, int16_t c){
uint32_t x = 0;
uint16_t temp_a = 0, temp_b = 0, temp_c = 0;
temp_a = a << 24;
temp_b = b << 4;
temp_c = c << 4;
x = temp_a|temp_b|temp_c;
return x;
}
Essentially what I'm trying to do is fill the 32-bit number with bit information that I can extract at a later time to perform different operations.
Parameter a would hold the first 24 bits of "data", b would hold the next 4 bits of "data" and c would hold the final 4 bits of "data".
I have a couple questions:
Do the parameters have to be the same bit length as the function type, and must they be unsigned?
Can I assign an unsigned int to a signed int? (i.e. uint32_t a = int32_t b;)
Can I fill a 32-bit number with the 16-bit parameters so long they don't exceed the length of the 32-bit return value.
Any advice/tips/hints would be much appreciated, thank you.
A correct way to write this code is:
uint32_t fillThisNum(uint32_t a, uint32_t b, uint32_t c)
{
// mask out the bits we are not interested in
a &= 0xFFFFFF; // save lowest 24 bits
b &= 0xF; // save lowest 4 bits
c &= 0xF; // save lowest 4 bits
// arrange a,b,c within a 32-bit unit so that they do not overlap
return (a << 8) + (b << 4) + c;
}
By using an unsigned type for the parameters, you avoid any issues with signed arithmetic overflow, sign extension, etc.
It's OK to pass signed values as arguments when calling the function, those values will be converted to unsigned.
By using uint32_t as the parameter type then you avoid having to declare any temporary variables or worry about type width when doing your casting. It makes it easier for you to write clear code, this way.
You don't have to do it this way but this is a simple way to make sure you don't make any mistakes.
Do the parameters have to be the same bit length as the function type, and must they be unsigned?
No, the arguments and the return value can be different types.
Can I assign an unsigned int to a signed int? (i.e. uint32_t a = int32_t b;)
Yes, the value will be converted from a signed to an unsigned value. The bits in "b" will stay the same, so while "b" is in 2's complement, "a" will be a positive 32-bit number.
So, for example, let int8_t c = -127. If you perform an assignment uint8_t d = c, then "d" will be 129.
Can I fill a 32-bit number with the 16-bit parameters so long they don't exceed the length of the 32-bit return value.
If by that, you mean the way that you did in your code:
x = temp_a|temp_b|temp_c;
Yes, that is fine, with the caveat that #chux mentioned: you can't shift an n-bit value more than n bits. If you wanted to set bits more significant than bit 15 in x, a way to do this would be to set up one of the temp masks with a 32-bit value instead of a 16-bit one.

Left Bit Shift In C without extension

I was wondering how to get C to not extend my binary number when I bitshift to the left
int main ()
{
unsigned int binary_temp = 0b0100;
binary_temp = binary_temp << 2;
printf("%d", binary_temp);
return 0;
}
When I run that I want a return value of 0 since it has extended past the 4 digits I have, but right now it returns 16 (10000). How would I get C not to extend my number?
Edit: I would like to be able to work with the number in binary form so I need to have only 4 digits, and not just outputting the right number.
It does not extend your number but saves it as unsigned int type which is 4 bytes (32 bits) in size. You only fill the last 4 bits. To treat it as only 4 bits, use Bitwise AND with a Mask value. Here's example code:
int main()
{
unsigned int binary_temp = 0b0100;
binary_temp = (binary_temp << 2) & 0b1111;
printf("%u", binary_temp);
return 0;
}
You can bitwise AND the result with a 4 bit mask value:
binary_temp = (binary_temp << 2) & 0xF;
There is no 0b in standard C. You could use 4.
unsigned int /* prepare for wtf identifier: */
binary_temp = 4;
Left shifting by 2 is multiplying by 4. Why not?
binary_temp *= 4;
... and then reduce modulo 16?
binary_temp %= 16;
What sense is there to using binary operators, in this case? I see none.
The %d directive corresponds to an int argument, but the argument you're giving printf is an unsigned int. That's undefined behaviour.
printf("%u", binary_temp);
I'm sure whichever book you're reading will tell you about the %u directive.

Resources