Unexpected Output in right shift bitwise operation - c

int main()
{
int x = 0xff0000ff;
int N_BITS = sizeof (int) * 8; /* 32 */
int l = 0x0;
printf ("Right shift expected result: %x\n", 0x80000000 >> (31));
l = (x & (0x00000001 << (N_BITS - 1)));
printf ("l = %x\n", l);
/* Right Shift l by 31 bits */
l = l >> 31;
printf ("l after right shift by 31 bits: %x\n", l);
}
~
Output:
Right shift expected result: 1
l = 80000000
l after right shift by 31 bits: ffffffff
~
The right shift of 0x80000000 by 31 bits should result in 0x00000001 as shown in the very first output. Why the output is different here when the variable l is shifted by 31 bits to the right?

Assuming the result of
l = (x & (0x00000001 << (N_BITS - 1)));
is 0x80000000 (see below it is not guaranteed as the expression invokes undefined behavior).
In two's complement system, 0x80000000 is a negative value (INT_MIN).
l = l >> 31;
C says this >> operation is implementation-defined. In your system it performs sign extension: the sign bit is propagated.
(C11, 6.5.7p4) "If E1 has a signed type and a negative value, the
resulting value is implementation-defined."
Finally on why:
0x000001 << (N_BITS - 1)
invokes undefined behavior.
From the horse mouth (emphasis mine):
(C11, 6.5.7p4) "The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2^^E2, reduced modulo
one more than the maximum value representable in the result type. If E1 has a signed
type and nonnegative value, and E1 × 2^^E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined."

Related

How do I resolve the following error in my bit shifting C code?

Can anyone help me with the below? Say I have the binary value int colour which is 255 or i.e.
00000000 00000000 000000000 11111111
in binary. How can I perform shifting to get
11111111 11111111 11111111 00000000
I tried making 4 values of 0xff, 0xff00, 0xff0000, 0xff000000 and was going to OR them but when I print these values out I get the following error:
converter.c:66:23: runtime error: left shift of 255 by 24 places cannot be represented in type 'int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior converter.c:66:23
in
VALS ARE ff, ff00, ff0000, ff000000
Below is my code any help would be greatly appreciated
int val1 = colour;
int val2 = (colour << 8);
int val3 = (colour << 16);
int val4 = (colour << 24);
//unsigned int val5 = 0;
printf("VALS ARE %x, %x, %x, %x\n" , val1, val2, val3, val4);
//rowElement(colour, sketch);
You're getting an error because you're shifting a value into the sign bit of an int. If you shift a 1 into that bit, you trigger undefined behavior.
This is described in section 6.5.7p4 of the C standard regarding bitwise shift operators:
The result of E1 << E2 is E1 left-shifted E2 bit positions;
vacated bits are filled with zeros. If E1 has an unsigned type,
the value of the result is E1 × 2E2, reduced modulo one more
than the maximum value representable in the result type. If E1
has a signed type and nonnegative value, and E1 × 2E2 is
representable in the result type, then that is the resulting
value; otherwise, the behavior is undefined.
Change the type of each of your variables to unsigned int. Then you can freely shift into any of the bits, as long as you don't shift by 32 bits or more, assuming an int is 32 bits.
It is enough to write
int x = 255;
x ~= x;
Or it will be better to declare the variable x as having the type unsigned int.
unsigned int x = 255;
x ~= x;
As for the shift operator then according to the C Standard (6.5.7 Bitwise shift operators)
4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated
bits are filled with zeros. If E1 has an unsigned type, the value of
the result is E1 × 2E2, reduced modulo one more than the maximum value
representable in the result type. If E1 has a signed type and
nonnegative value, and E1 × 2E2 is representable in the result type,
then that is the resulting value; otherwise, the behavior is
undefined.
To reverse the bytes in ARGB color or any 32-bit unsigned integer, shift to the right, then AND with 0xff For example, to get 44 from 0x11223344 we need just 0x11223344 & 0xff To get 33, shift right by 8 bits -> 0x00112233 and then AND with 0xff again.
Left-shift is needed to build a 32-bit integer again.
int main(void)
{
unsigned int colour = 0x11223344;
unsigned char byte0, byte1, byte2, byte3;
byte0 = (colour ) & 0xff;
byte1 = (colour >> 8 ) & 0xff;
byte2 = (colour >> 16) & 0xff;
byte3 = (colour >> 24) & 0xff;
unsigned int reversed = byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3;
printf("%08X\n", colour);
printf("%08X\n", reversed);
return 0;
}
Output
11223344
44332211

Bit shift with a signed int resets one bit too much

Please have a look at the following code snippet, which basically simply bit shifts 1 byte by 24 bits to the left.
uint64_t i = 0xFFFFFFFF00000000;
printf("before: %016llX \n", i);
i += 0xFF << 24;
printf("after : %016llX \n", i);
// gives:
// before: FFFFFFFF00000000
// after : FFFFFFFEFF000000
The most significant 32 bits are FFFFFFFE (watch the E at the end). This is not as I expected. I don't see why shifting 1 bytes 24 bits left would touch bit #32 (bit #31 should be the last one modified) It changed the last F (1111) into E (1110)).
To make it work properly, I had use 0xFF unsigned (0xFFU).
uint64_t i = 0xFFFFFFFF00000000;
printf("before: %016llX \n", i);
i += 0xFFU << 24;
printf("after : %016llX \n", i);
// gives:
// before: FFFFFFFF00000000
// after : FFFFFFFFFF000000
Why does the bit shift with a signed int (0xFF) touch/reset one bit too much?
You left-shifted into the sign bit.
The integer constant 0xFF has type int. Assuming an int is 32 bit, the expression 0xFF << 24 shifts a bit set to 1 into the high-order bit of a signed integer triggers undefined behavior which in your case manifested as an unexpected value.
This is spelled out in section 6.5.7p4 of the C standard:
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1×2E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1×2E2is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
By using the U suffix this makes the constant have type unsigned int, and it is valid to shift bits set to 1 into the high-order bit because there is no sign bit.

Bit Shifting: Shift Count >= Width Of Type

The code below, when compiled, throws a warning caused by line 9:
warning: shift count >= width of type [-Wshift-count-overflow]
However, line 8 does not throw a similar warning, even though k == 32 (I believe). I'm curious why this behavior is occurring? I am using the gcc compiler system.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int bit_shift(unsigned x, int i){
int k = i * 8;
unsigned n = x << k; /* line 8 */
unsigned m = x << 32; /* line 9 */
return 0;
}
int main(){
bit_shift(0x12345678, 4);
return 0;
}
The value of k in bit_shift is dependent on the parameter i. And because bit_shift is not declared static it is possible that it could be called from other translation units (read: other source files).
So it can't determine at compile time that this shift will always be a problem. That is in contrast to the line unsigned m = x << 32; which always shifts by an invalid amount.
I think why Line 8 does not throw a warning is because left shifting an unsigned int32 >= 32 bits is NOT an undefined behavior.
C standard (N2716, 6.5.7 Bitwise shift operators) says:
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined

Unusual behavior with shift-right bitwise operator

I'm writing a simple code in C (only using bit-wise operators) that takes a pointer to an unsigned integer x and flips the bit at the nth position n in the binary notation of the integer. The function is declared as follows:
int flip_bit (unsigned * x, unsigned n);
It is assumed that n is between 0 and 31.
In one of the steps, I perform a shift-right operation, but the results are not what I expect. For instance, if I do 0x8000000 >> 30, I get 0xfffffffe as a result, which are 1000 0000 ... 0000 and 1111 1111 ... 1110, respectively, in binary notation. (The expected result is0000 0000 ... 0010).
I am unsure of how or where I am making the mistake. Any help would be appreciated. Thanks.
Edit 1: Below is the code.
#include <stdio.h>
#define INTSIZE 31
void flip_bit(unsigned * x,
unsigned n) {
int a, b, c, d, e, f, g, h, i, j, k, l, m, p, q;
// save bits on the left of n and insert a zero at the end
a = * x >> n + 1;
b = a << 1;
// save bits on the right of n
c = * x << INTSIZE - (n - 1);
d = c >> INTSIZE - (n - 1);
// shift the bits to the left (back in their positions)
// combine all bits
e = d << n;
f = b | e;
// Isolating the nth bit in its position
g = * x >> n;
h = g << INTSIZE;
// THIS LINE BELOW IS THE ONE CAUSING TROUBLE.
i = h >> INTSIZE - n;
// flipping all bits and removing the 1s surrounding
// the nth bit (0 or 1)
j = ~i;
k = j >> n;
l = k << INTSIZE;
p = l >> INTSIZE - n;
// combining the value missing nth bit and
// the one with the flipped one
q = f | p;
* x = q;
}
I'm getting the unusual behavior when I run flip_bit(0x0000004e,0). The line for the shift-right operation in question has comments in uppercase above it.
There is probably a shorter way to do this (without using a thousand variables), but that's what I have now.
Edit 2: The problem was that I declared the variables as int (instead of unsigned). Nevertheless, that's a terrible way to solve the question. #old_timer suggested returning *x ^ (1u << n), which is much better.
The issue here is that you're performing a right shift on a signed int.
From section 6.5.7 of the C standard:
5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative
value, the value of the result is the integral part of the quotient of
E1 / 2E2. If E1 has a signed type and a negative value, the
resulting value is implementation-defined.
The bold part is what's happening in your case. Each of your intermediate variables are of type int. Assuming your system uses 2's complement representations for negative numbers, any int value with the high bit set is interpreted as a negative value.
The most common implementation-defined behavior behavior you'll see (and this in fact what gcc and MSVC both do) in this case is that if the high bit is set on a signed value then a 1 will be shifted in on a right shift. This preserves the sign of the value and makes x >> n equivalent to x / 2n for all signed and unsigned values.
You can fix this by changing all of your intermediate variables to unsigned. That way, they match the type of *x and you won't get 1s pushed on to the left.
As for your method of flipping a bit, there is a much simpler way of doing so. You can instead use the ^ operator, which is the bitwise exclusive OR operator.
From section 6.5.11 of the C standard:
4 The result of the ^ operator is the bitwise exclusive OR (XOR) of the
operands (that is, each bit in the result is set if and only if
exactly one of the corresponding bits in the converted operands is
set).
For example:
0010 1000
^ 1100 ^ 1101
------ ------
1110 0101
Note that you can use this to create a bitmask, then use that bitmask to flip the bits in the other operand.
So if you want to flip bit n, take the value 1, left shift it by n to move that bit to the desired location then XOR that value with your target value to flip that bit:
void flip_bit(unsigned * x, unsigned n) {
return *x = *x ^ (1u << n);
}
You can also use the ^= operator in this case which XORs the right operand to the left and assigns the result to the left:
return *x ^= (1u << n);
Also note the u suffix on the integer constant. That causes the type of the constant to be unsigned which helps to avoid the implementation defined behavior you experienced.
#include <stdio.h>
int main ( void )
{
unsigned int x;
int y;
x=0x80000000;
x>>=30;
printf("0x%08X\n",x);
y=0x80000000;
y>>=30;
printf("0x%08X\n",y);
return(0);
}
gcc on mint
0x00000002
0xFFFFFFFE
or what about this
#include <stdio.h>
int main ( void )
{
unsigned int x;
x=0x12345678;
x^=1<<30;
printf("0x%08X\n",x);
}
output
0x52345678

Why the same bitwise operations give different results?

Trying to turn off the MSB with all other bits on.
unsigned char a = ~0 << 1 >> 1;
printf("a: %d\n", a);
unsigned char b = ~0;
b <<= 1;
b >>= 1;
printf("b: %d\n", b);
The printout gives:
a: 255
b: 127
Integer promotion rules apply.
The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand.
The RHS of the initialization:
unsigned char a = ~0 << 1 >> 1;
converts 0 to int, then does bitwise left and right shifts, and then finally the assignment converts the result to unsigned char. This means that the result will be 255 (assuming CHAR_BIT == 8). Technically, you have undefined behaviour:
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with
zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo
one more than the maximum value representable in the result type. If E1 has a signed
type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined.
You would avoid undefined behaviour if you used:
unsigned char a = ~0U << 1 >> 1;
The 'multiple assignments' version (avoiding undefined behaviour) is equivalent to:
unsigned char a = (unsigned char)(~0U << 1) >> 1;
which truncates the result of the left shift before re-promoting the type for the right shift, and would yield 127 as the result (still assuming CHAR_BIT == 8).

Resources