C++ Int bit manipulating is 2UL = 10UL? - c++

I have a quick question.
I've been playing around with bit manipulation in c/c++ for a while and I recently discovered that when I compare 2UL and 10UL to a regular unsigned int they seem to return the same bit.
For example,
#define JUMP 2UL
#define FALL 10UL
unsigned int flags = 0UL;
this->flags |= FALL;
//this returns true
this->is(JUMP);
bool Player::is(const unsigned long &isThis)
{
return ((this->flags & isThis) == isThis);
}
Please confirm if 2U equals 10U and if so, how would I go around it if I need more than 8(?) flags in a single unsigned integer.
Kind regards,
-Markus

Of course. 10ul is 1010 in binary and 2 is 10. Therefore, doing x |= 10 sets the second bit too.
You probably wanted to use 0x10 and 0x2 as your flags. These would work as you expect.
As an aside: a single digit in the hex notation represent 4 bits, not 8.

JUMP, 2: 0010
FALL, 10: 1010
FALL & JUMP = JUMP = 0010

Decimal 2 in binary is 0010, whereas decimal 10 is binary 1010. If you bitwise-and them (2 & 10), that yields binary 0010, or decimal 2. So 10 & 2 is indeed equal to 2. Maybe your intention is to test for 1ul << 2 and 1ul << 10, which would be bits number 2 and 10 respectively. Or maybe you meant to use hexadecimal 10, (decimal 16, binary 10000), which is denoted as 0x10.

Related

What does 0b1 mean in C++?

I came across a part of code that I cannot understand.
for (unsigned int i = (x & 0b1); i < x; i+= 2)
{
// body
}
Here, x is from 0 to 5.
What is meant by 0b1? and what would be the answers for eg: (0 & 0b1), (4 & 0b1) etc?
0b... is a binary number, just like 0x... is hex and 0... is octal.
Thus 0b1 is same as 1.
1b0 is illegal, the first digit in those must always be 0.
As previous answers said, it is the binary representation of the integer number 1, but they don't seem to have fully answered your question. This has a lot of layers so I'll briefly explain each.
In this context, the ampersand is working as a bitwise AND operator. i & 0b1 is (sometimes) a faster way of checking if an integer is even as opposed to i % 2 == 0.
Say you have int x = 5 and you'd like to check if it's even using bitwise AND.
In binary, 5 would be represented as 0101. That final 1 actually represents the number 1, and in binary integers it's only present in odd numbers. Let's apply the bitwise AND operator to 5 and 1;
0101
0001
&----
0001
The operator is checking each column, and if both rows are 1, that column of the result will be 1 – otherwise, it will be 0. So, the result (converted back to base10) is 1. Now let's try with an even number. 4 = 0100.
0100
0001
&----
0000
The result is now equal to 0. These rules apply to every single integer no matter its size.
The higher-level layer here is that in C, there is no boolean datatype, so booleans are represented as integers of either 0 (false) or any other value (true). This allows for some tricky shorthand, so the conditional if(x & 0b1) will only run if x is odd, because odd & 0b1 will always equal 1 (true), but even & 0b1 will always equal 0 (false).

C/C++ Bitwise Operations not resulting in expected output?

I'm currently working on bitwise operations but I am confused right now... Here's the scoop and why
I have a byte 0xCD in bits this is 1100 1101
I am shifting the bits left 7, then I'm saying & 0xFF since 0xFF in bits is 1111 1111
unsigned int bit = (0xCD << 7) & 0xFF<<7;
Now I would make the assumption that both 0xCD and 0xFF would get shifted to the left 7 times and the remaining bit would be 1&1 = 1 but I'm not getting that for output also I would also make the assumption that shifting 6 would give me bits 0&1 = 0 but I'm getting again a number above 1 like 205 0.o Is there something incorrect about the way I am trying to process bit shifting in my head? If so what is it that I am doing wrong?
Code Below:
unsigned char byte_now = 0xCD;
printf("Bits for byte_now: 0x%02x: ", byte_now);
/*
* We want to get the first bit in a byte.
* To do this we will shift the bits over 7 places for the last bit
* we will compare it to 0xFF since it's (1111 1111) if bit&1 then the bit is one
*/
unsigned int bit_flag = 0;
int bit_pos = 7;
bit_flag = (byte_now << bit_pos) & 0xFF;
printf("%d", bit_flag);
Is there something incorrect about the way I am trying to process bit shifting in my head?
There seems to be.
If so what is it that I am doing wrong?
That's unclear, so I offer a reasonably full explanation.
In the first place, it is important to understand that C does not not perform any arithmetic directly on integers smaller than int. Consider, then, your expression byte_now << bit_pos. "The usual arithmetic promotions" are performed on the operands, resulting in the left operand being converted to the int value 0xCD. The result has the same pattern of least-significant value bits as bit_flag, but also a bunch of leading zero bits.
Left shifting the result by 7 bits produces the bit pattern 110 0110 1000 0000, equivalent to 0x6680. You then perform a bitwise and operation on the result, masking off all but the least-significant 8 bits, thus yielding 0x80. What happens when you assign that to bit_flag depends on the type of that variable, but if it is an integer type that is either unsigned or has more than 7 value bits then the assignment is well-defined and value-preserving. Note that it is bit 7 that is nonzero, not bit 0.
The type of bit_flag is more important when you pass it to printf(). You've paired it with a %d field descriptor, which is correct if bit_flag has type int and incorrect otherwise. If bit_flag does have type int, then I would expect the program to print 128.

Shifting more than 8 bits - leading to wrong output

I am trying to perform this operation, and im getting the wrong output.
signed char temp3[3] = {0x0D, 0xFF, 0xC0};
double temp = ((temp3[0] & 0x03) << 10) | (temp3[1]) | ((temp3[2] & 0xC0) >> 6)
I am trying to form a 12 bit number. get the last 2 bits of 0x0D, all 8 of 0xFF and first 2 of 0xC0 to form the binary number (011111111111) = 2047, however I am getting -1. When I break the first mask and shift of 10, I get 0. I dont know if this is my problem, trying to shift an 8 bit character 10 bits.
When bit twiddling, always use unsigned numbers.
Change the array to unsigned char.
Add the 'U' suffix to each constant, because each constant is a signed integer by default.
BTW, right shifting is undefined implementation defined for signed integers.
Per comments, changed "undefined" to "implementation defined".
There are a few things you need to address.
First up, c++ doesn't have 12 bit numbers. The best you can have are 16 bit. The top bit represents sign in twos complement form.
You also need to be very careful shift of the type of the number you are shifting. In your example, you are left shifting a char by over 8 bits. As a char is only 8 bits, you are zeroing it.
The following example gives a correct implmentation (for signed 12 bit numbers). There are no doubt more efficient ones.
// shift in top 2 bits
signed short test = static_cast<signed short>(temp3[0] & 0x03) << 10 ;
// shift in middle 8 bits
test |= (static_cast<signed short>(temp3[1]) << 2) & 0x03FC;
// rightshift, mask and append lower 2 bits
test |= (static_cast<signed short>(temp3[2]) >> 6) & 0x0003;
// sign extend top bits from 12 bits to 16 bits
test |= (temp3[0] & 0x02) == 0 ? 0x0000 : 0xF0000;

How to get the least significant 3 bits of a char in C++?

The following text is what I'm stuck with on a piece of documentation.
The least significant 3 bits of the first char of the array indicates whether
it is A or B. If the 3 bits are 0x2, then the array is in a A
format. If the 3 bits are 0x3, then the array is in a B format.
This is the first time in my life I have ever touched on with this least significant bits thingy. After searching on StackOverflow, this is what I did:
int lsb = first & 3;
if (lsb == 0x02)
{
// A
}
else if (lsb == 0x03)
{
// B
}
Is this correct? I want to ensure this is the right way (and avoid blowing my foot off later) before I move on.
The least significant 3 bits of x are taken using x&7 unlike the first & 3 you use. In fact first & 3 will take the least significant 2 bits of first.
You should convert the numbers to binary to understand why this is so: 3 in binary is 11, while 7 is 111.
Normally, 3 least significant bits should be yourchar&0x07 unstead.
7 because 7 is 1+2+4 or binary 111, corresponding to the 3 LSB.
EDIT: grilled, should be deleted. Sorry.
The variable you need will have every bit zero and three LSBs 1, which is 0111 in short.
0111 is 0x7, use variable & 0x7 to mask your variable.
Google bit masking for more information about it.
d3 = b11 = b01 | b10
So no, right now you're comparing only the 2 LSBs. b111 would be d7
If you want to write down the number of bits to take, You'd have to write it as
unsigned int ls3b = ~(UINT_MAX << 3);
what this does is, it takes the all 1 bit array, shifts it by 3 bits to the left (leaving the 3 LSBs 0) and then inverts it.

How is this size alignment working

I am not able to understand the below code with respect to the comment provided. What does this code does, and what would be the equivalent code for 8-aligned?
/* segment size must be 4-aligned */
attr->options.ssize &= ~3;
Here, ssize is of unsigned int type.
Since 4 in binary is 100, any value aligned to 4-byte boundaries (i.e. a multiple of 4) will have the last two bits set to zero.
3 in binary is 11, and ~3 is the bitwise negation of those bits, i.e., ...1111100. Performing a bitwise AND with that value will keep every bit the same, except the last two which will be cleared (bit & 1 == bit, and bit & 0 == 0). This gives us a the next lower or equal value that is a multiple of 4.
To do the same operation for 8 (1000 in binary), we need to clear out the lowest three bits. We can do that with the bitwise negation of the binary 111, i.e., ~7.
All powers of two (1, 2, 4, 8, 16, 32...) can be aligned by simple a and operation.
This gives the size rounded down:
size &= ~(alignment - 1);
or if you want to round up:
size = (size + alignment-1) & ~(alignment-1);
The "alignment-1", as long as it's a value that is a power of two, will give you "all ones" up to the bit just under the power of two. ~ inverts all the bits, so you get ones for zeros and zeros for ones.
You can check that something is a power of two by:
bool power_of_two = !(alignment & (alignment-1))
This works because, for example 4:
4 = 00000100
4-1 = 00000011
& --------
0 = 00000000
or for 16:
16 = 00010000
16-1 = 00001111
& --------
0 = 00000000
If we use 5 instead:
5 = 00000101
4-1 = 00000100
& --------
4 = 00000100
So not a power of two!
Perhaps more understandable comment would be
/* make segment size 4-aligned
by zeroing two least significant bits,
effectively rounding down */
Then at least for me, immediate question pops to my mind: should it really be rounded down, when it is size? Wouldn't rounding up be more appropriate:
attr->options.ssize = (attr->options.ssize + 3) & ~3;
As already said in other answers, to make it 8-aligned, 3 bits need to be zeroed, so use 7 instead of 3. So, we might make it into a function:
unsigned size_align(unsigned size, unsigned bit_count_to_zero)
{
unsigned bits = (1 << bit_count_to_zero) - 1;
return (size + bits) & ~bits;
}
~3 is the bit pattern ...111100. When you do a bitwise AND with that pattern, it clears the bottom two bits, i.e. rounds down to the nearest multiple of 4.
~7 does the same thing for 8-aligned.
The code ensures the bottom two bits of ssize are cleared, guaranteeing that ssize is a multiple of 4. Equivalent code for 8-aligned would be
attr->options.ssize &= ~7;
number = number & ~3
The number is rounded off to the nearest multiple of 4 that is lesser than number
Ex:
if number is 0,1,2 or 3, the `number` is rounded off to 0
similarly if number is 4,5,6,or 7,numberis rounded off to 4
But if this is related to memory alignment, the memory must be aligned upwards and not downwards.