right-shifting unsigned char is filling with ones? - c++

On my system, (unsigned char) -1 is (expectedly for chars of 8 bits) 1111 1111 in binary (255 decimal).
Similarly, (unsigned char) -1 >> 1 is as expected 0111 1111. The left was filled with a zero.
~((unsigned char) -1 >> 1) is 1000 0000 as expected.
Now I want to generate the unsigned char 0010 0000 for example.
I tried ~((unsigned char) -1 >> 1) >> 2, but this outputs 1110 0000 .... what the? Why is the left being filled with ones all of a sudden?
How can I generate an unsigned char with the nth bit (from the left) enabled?
I would like
n unsigned char
0 1000 0000
1 0100 0000
2 0010 0000
3 0001 0000
...
7 0000 0001
At the moment, ~((unsigned char) -1 >> 1) >> n is giving me
n unsigned char
0 1000 0000
1 1100 0000
2 1110 0000
3 1111 0000
...
7 1111 1111
This problem exists for uint8_t, uint16_t, but no longer happens at uint32_t and greater.

Due to integer promotions, unsigned char is promoted to int when pretty much any operation is performed on the value.
When you shift right the left operand undergoes integer promotions, and unsigned char would become int. The value of the expression will be that of the left operand after promotions - therefore the result of ((unsigned char) -1 >> 1) has value 127, of type int. If you ~ (int)127 you'll get an int with sign-bit set; shifting that right will have implementation-defined behaviour.
The solution is to add a cast around the outer ~:
(unsigned char)~((unsigned char) -1 >> 1) >> 2
Or alternatively, & the value with 0xFF:
(~((unsigned char) -1 >> 1) >> 2) & 0xFF
As for setting the nth bit from left of unsigned char, the best solution is to *left-shift 1U to the position, as shown by Allan Wind.

Another way to set the nth bit (from the left):
1 << (CHAR_BIT - n - 1)

You might take advantage of std::numeric_limits<T>::digits to create a less obfuscated and flexible code:
unsigned char data=0;
const uint8_t sizeBit=std::numeric_limits<decltype(data)>::digits;
for(uint8_t n=0;n<sizeBit;n++) {
data = 1 << (sizeBit - (n+1));
std::bitset<sizeBit> x(data);
std::cout << x << '\n';
}
Prints:
10000000
01000000
00100000
00010000
00001000
00000100
00000010
00000001

Related

Casting two bytes to a 12 bit short value?

I have a buffer which consists of data in unsigned char and two bytes form a 12 Bit value.
I found out that my system is little endian. The first byte in the buffer gives me on the console numbers from 0 to 255. The second byte gives always low numbers between 1 and 8 (measured data, so higher values up to 4 bit would be possible too).
I tried to shift them together so that I get an ushort with a correct 12 bit number.
Sadly at the moment I am totally confused about the endianess and what I have to shift how far in which direction.
I tried e.g. this:
ushort value =0;
value= (ushort) firstByte << 8 | (ushort) secondByte << 4;
Sadly the value of value is quite often bigger than 12 bit.
Where is the mistake?
It depends on how the bits are packed within the two bytes exactly, but the solution for the most likely packing would be:
value = firstByte | (secondByte << 8);
This assumes that the second byte contains the 4 most significant bits (bits 8..11), while the first byte contains the 8 least significant bits (bits 0..7).
Note: the above solution assumes that firstByte and secondByte are sensible unsigned types (e.g. uint8_t). If they are not (e.g. if you have used char or some other possibly signed type), then you'll need to add some masking:
value = (firstByte & 0xff) | ((secondByte & 0xf) << 8);
I think the main issue may not be with the values you're shifting alone. If these values are greater than their representative bits, they'll create a large value unless "and'd" out.
picture the following
0000 0000 1001 0010 << 8 | 0000 0000 0000 1101 << 4
1001 0010 0000 0000 | 0000 0000 1101 0000
You should notice the first problem here. The first 4 'lowest' values are not being used, and it's using up 16 bits. you only wanted twelve. This should be modified like so:
(these are new numbers to demonstrate something else)
0000 1101 1001 0010 << 8 | 0000 0000 0000 1101
1101 1001 0010 0000 | (0000 0000 0000 1101 & 0000 0000 0000 1111)
This will create the following value:
1101 1001 0010 1101
here, you should note that the value is still greater than the 12 bits. If your numbers don't extend passed the original 8bit, 4 bit size ignore this. Otherwise, you have to use the 'and' operation on the bits to eliminate the left most 4 bits.
0000 1111 1111 1111 & 0000 1001 0010 1101
These values can be created using either 0bXX macros, the 2^bits - 1 pattern, as well as various other forms.

How does 1 left shift by 31 (1 << 31) work to get maximum int value? Here are my thoughts and some explanations I found online

I'm fairly new to bit manipulation and I'm trying to figure out how (1 << 31) - 1 works.
First I know that 1 << 31 is
1000000000000000000000000000
and I know it's actually complement of minimum int value, but when I tried to figure out (1 << 31) - 1, I found an explanation states that, it's just
10000000000000000000000000000000 - 1 = 01111111111111111111111111111111
I was almost tempted to believe it since it's really straightforward. But is this what really happening? If it's not, why it happens to be right?
My original thought was that, the real process should be: the two's complement of -1 is
11111111111111111111111111111111
then (1 << 31) - 1 =
(1)01111111111111111111111111111111
the leftmost 1 is abandoned, then we have maximum value of int.
I'm really confused about which one is right.
It's both! 1 << 31 is:
1000 0000 0000 0000 0000 0000 0000 0000
Subtracting 1 gives:
0111 1111 1111 1111 1111 1111 1111 1111
One of the nice features about the two's complement layout of signed numbers is that addition and subtraction are exactly the same operations as they are for unsigned numbers. So 10000...000 represents a negative number in two's complement, the largest negative number, which is -2,147,483,648 in this case, and subtracting 1 from it causes wrap-around to the largest positive number, 2,147,483,647, but two's complement numbers are arranged so that we can pretend it's an unsigned number instead, so the subtraction is uncomplicated. Subtracting 1 from 10000...000 simply drops the leading 1 to a 0, and borrows a bunch of 1s, same as in decimal you get a bunch of 9s: 10000 - 1 = 9999.
It's also true that mathematically, (a - b) is the same as (a + (-b)), so we can do (1 << 31) + (-1) instead:
1000 0000 0000 0000 0000 0000 0000 0000 (1 << 31)
1111 1111 1111 1111 1111 1111 1111 1111 (-1)
-----------------------------------------
1 0111 1111 1111 1111 1111 1111 1111 1111 +
0111 1111 1111 1111 1111 1111 1111 1111 (truncate)
A 1 is carried out of the high end, and lost once the result is truncated back into a 32-bit integer.
Either way, that pattern, with a single 0 at the high end, then filled by 1s, is the representation of the maximum positive value for a two's complement integer of any width.
There are other ways to generate that pattern if you prefer, such as ~(1 << 31), and (-1 >>> 1) (where >>> means logical shift right) which is agnostic of the width of the integer.

Shift instructions in Golang

The go spec says:
<< left shift integer << unsigned integer
What if the left side is type of uint8:
var x uint8 = 128
fmt.Println(x << 8) // it got 0, why ?
fmt.Println(int(x)<<8) // it got 32768, sure
Questions:
when x is uint8 type, why no compile error?
why x << 8 got result 0
For C/C++,
unsigned int a = 128;
printf("%d",a << 8); // result is 32768.
Could anyone explain? Thank you.
The left shift operator is going to shift the binary digits in the number to the left X number of places. This has the effect of adding X number of 0's to the right hand side the number A unit8 only holds 8 bits so when you have 128 your variable has
x = 1000 0000 == 128
x << 8
x= 1000 0000 0000 0000 == 32768
Since uint8 only holds 8 bits we tak the rightmost 8 bits which is
x = 0000 0000 == 0
The reason you get the right number with an int is an int has at least 16 bits worth of storage and most likely has 32 bits on your system. That is enough to store the entire result.
Because uint8 is an unsigned 8-bit integer type. That's what "u" stands for.
Because uint8(128) << 8 shifts the value, turning 1000 0000 into 0000 0000.
int(x) makes it 0000 0000 0000 0000 0000 0000 1000 0000 (on 32 bit systems, since int is architecture-dependant) and then the shift comes, making it 0000 0000 0000 0000 1000 0000 0000 0000, or 32768.

Convert bit sequence to uint32_t in c++

User specifies register (LFSR) length with integer as a parameter for a function, for example he enters number 5. I need to initialize this 5-bit length LFSR with all 1 bits (for length 5 it will be 11111) and get a seed mask in a format uint32_t - for 5-length register it will be 0x0001f.
What is the best way to get mask 0x0001f for 5 bit length register when a user enters only length of the register as an integer number 5?
To generate a mask of n bits (where n < 32):
uint32_t mask = (1U << n) - 1U;
Explanation: consider the example where n = 5:
1U << n = 1U << 5 = 0000 0000 0000 0000 0000 0000 0010 0000 = 0x20
then we subtract 1 and get:
0000 0000 0000 0000 0000 0000 0001 1111 = 0x1f
Another option is
std::uint32_t mask = ~(~0U << n);
Also you have to make sure unsigned int isn't less than 32 bits on your system, it may be better to write
std::uint32_t mask = ~(~(std::uint32_t)0 << n);

How is it that an unsigned integer array can contain a negative integer?

I wrote this piece of code just to see what would happen if I put a negative integer into an unsigned integer array.
#include <iostream>
int main()
{
using namespace std;
unsigned int array[4];
array[0]=4;
array[1]=4;
array[2]=2;
array[3]=-2;
cout << array[0] + array[1] + array[2] + array[3] << endl;
unsigned int b;
b=-2;
cout << b <<endl;
return 0;
}
I was expecting integer overflow to occur in both the cases. However, only in the second case that actually happened. In the first case, everything behaved as if it were an oridinary integer array, not an unsigned integer array. So what exactly is happening that's causing this anomalous behaviour. My compiler is gcc 4.8 in cases that's of any importance. Thank you for your help. EDIT: Here's th output on my computer
8
4294967294
There is an integer overflow. Here is the reason ( the numbers are converted to unsigned int)
1111 1111 1111 1111 1111 1111 1111 1110 // -2
+0000 0000 0000 0000 0000 0000 0000 0100 //+ 4
-------------------------------------------
0000 0000 0000 0000 0000 0000 0000 0010 //= 2
+0000 0000 0000 0000 0000 0000 0000 0100 //+ 4
-------------------------------------------
0000 0000 0000 0000 0000 0000 0000 0110 //= 6
+0000 0000 0000 0000 0000 0000 0000 0010 //+ 2
-------------------------------------------
0000 0000 0000 0000 0000 0000 0000 1000 //= 8 -> the result
when you do (assuming unsigned int is uint32_t):
array[0] = 4;
array[1] = 4;
array[2] = 2;
array[3] = -2; // You store 4294967294 here
And here array[0] + array[1] + array[2] + array[3] is equal to 4294967304 which don't fit in an uint32_t 0x1 0000 0008 which result in 8.
For the signed integers, the last bit is used to hold the sign value. So in your case, when you assign a negative integer to an unsigned integer, the last bit is taken up to represent the number rather than the sign value.
Negative numbers are usually represented in 2's complement form. So
11111110 is represented as −1 if signed
11111110 is represented as 254 if unsigned
Converting -2 to unsigned int results in the value 4294967294 (since unsigned int is 32 bits in the C++ implementation you're using).
unsigned int arithmetic is carried out modulo 4294967296 (or in general UINT_MAX+1). Hence in unsigned int, 4 + 4 + 2 + 4294967294 is 8.
Technically according to the standard this is not called "overflow", because the standard defines the result to depend only on the value of UINT_MAX. Overflow is the undefined behavior when signed integer arithmetic exceeds its bounds.
For signed integer, 31st bit is treated as sign bit (assuming 4 byte is integer size). For unsigned integers, there is no sign bit at all, i.e. each bit is contributes to the absolute value
You're seeing the result of (defined) unsigned integer overflow. Your -2 value becomes a very large unsigned integer, which when added to another unsigned integer, causes an overflow (the result is larger than the largest possible unsigned int value) with the effect that the result is 2 smaller than the other unsigned integer.
Eg:
unsigned int a = -2;
unsigned int b = 4;
unsigned int c = a + b; // result will be 2!