This question already has answers here:
Unexpected output when executing left-shift by 32 bits
(2 answers)
undefined behavior when left operand is negative
(3 answers)
Closed 8 years ago.
I'm debugging some code and came across some behavior I cannot explain.
I am trying to shift the number -1 to the left 32 times to produce a zero in this particular case.
int n = 0;
int negOne = ~0;
int negativeN = ( (~n) + 1 );
int toShift = (32 + negativeN); //32 - n
/*HELP!!! These produce two different answers*/
printf("%d << %d = %d \n",negOne, toShift, negOne << toShift);
printf("-1 << 32 = %d \n", -1 << 32) ;
Here is the what the console outputs:
-1 << 32 = -1
-1 << 32 = 0
I am not sure why the left shift is behaving differently in each of these cases.
It's undefined behavior because you shift count is bigger than the number of bits for an int, that means that the result can't be predicted.
When you Shift a number equal to or more than the number of its bit times your result can't be predictable! Simply it is Undefined_behavior.
If you compile your program with flags you will get warning for this shifting
Related
This question already has answers here:
Shifting a 32 bit integer by 32 bits
(2 answers)
Closed 7 years ago.
When shift count < width of type, it works as expected:
int a = 1 << (8 * sizeof(int) - 1);
printf("%x\n", a); // 80000000
When shift count >= width of type, the result is different every time and there seems no law:
int b = 1 << 8 * sizeof(int); // int b = 1 << (8 * sizeof(int) + 1);
printf("%x\n", b); // such as 59fa2ba8, 5b0f6ba8, 52f46ba8 etc
Well, there is a warning saying warning: shift count >= width of type [-Wshift-count-overflow]. If this can explain the random outcome, then let me put the shift count into a variable:
int k = 8 * sizeof(int);
int c = 1 << k;
int d = 1 << (k + 1);
printf("%x\n", c); // 1
printf("%x\n", d); // 2
The result is totally different from before, this is Circular shift! How to explain this?
int b = 1 << 8 * sizeof(int);
is subject to undefined behavior.
From the C99 Standard:
6.5.7 Bitwise shift operators
3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
It's pointless to try to make sense of the outcome of such an operation.
This question already has answers here:
What's bad about shifting a 32-bit variable 32 bits?
(5 answers)
Closed 7 years ago.
I am developing a simple C app on a CentOS linux machine my university owns and I am getting very strange inconsistent behavior with the << operator.
Basically I am attempting to shift 0xffffffff left based on a variable shiftNum which is based on variable n
int shiftNum = (32 + (~n + 1));
int shiftedBits = (0xffffffff << shiftNum);
This has the effect of shifting 0xffffffff left 32-n times and works as expected. However when n = 0 and shiftNum = 32 I get some very strange behaviour. Instead of getting the expected 0x00000000 I get 0xffffffff.
For example this script:
int n = 0;
int shiftNum = (32 + (~n + 1));
int shiftedBits = (0xffffffff << shiftNum );
printf("n: %d\n",n);
printf("shiftNum: 0x%08x\n",shiftNum);
printf("shiftedBits: 0x%08x\n",shiftedBits);
int thirtyTwo = 32;
printf("ThirtyTwo: 0x%08x\n",thirtyTwo);
printf("Test: 0x%08x\n", (0xffffffff << thirtyTwo));
Outputs:
n: 0
shiftNum: 0x00000020
shiftedBits: 0xffffffff
ThirtyTwo: 0x00000020
Test: 0x00000000
I have no idea what is going on honestly. Some crazy low-level something I suspect. Even more strange the operation (0xffffffff << (shiftNum -1)) << 1 outputs 0x00000000.
Does anyone have any clue whats going on?
If you invoke undefined behaviour, the results are unspecified and anything is valid.
When n is 0, 32 + (~n + 1) is 32 (on a two's complement CPU). If sizeof(shiftNum) == 4 (or sizeof(shiftNum) * CHAR_BIT == 32, which usually has the same result), then you are only allowed to shift by values 0..31; anything else is undefined behaviour.
ISO/IEC 9899:2011 ยง6.5.7 Bitwise shift operators:
If the value of the right operand is negative or is
greater than or equal to the width of the promoted left operand, the behavior is undefined.
The result, therefore, is correct โ even if you get a different answer each time you run the code, or recompile the program, or anything else.
This question already has answers here:
Why does combining two shifts of a uint8_t produce a different result?
(2 answers)
Closed 8 years ago.
I get a different result depending on if I combine multiple bitwise shifts on one line or put them on separate lines.
unsigned char a = 73;
a = (a << 6) >> 2;
printf("%d\n", a);
prints 144 when I expect 16
unsigned char a = 73;
a = a << 6;
a = a >> 2;
printf("%d\n", a);
prints the expected result of 16
when I shift left 6, then right 1 on one line, it prints the expected result of 32, so it
looks like the 2nd shift right is shifting in a 1 instead of a 0, but why?
Also
a = (unsigned char) (a << 6 ) >> 2;
produces the expected result (16).
Is the first left shift returning a signed char instead of an unsigned char, and if so why?
Yes, the result of the first shift is signed. signed int specifically. Check out the rules for the "integer promotions" in the C spec:
If an int can represent all values of the original type ... the value is converted to an int...
So, since your int - usually a range of [-231, 231) - can represent all the values of unsigned char - usually [0, 255] - it's converted to int, and the << and >> take place on the resulting values.
This question already has answers here:
In C bits, multiply by 3 and divide by 16
(5 answers)
Closed 8 years ago.
I need to multiply a number by 3/16, rounding to zero using only bitwise operations such as ! ~ & ^ | + << >>. So far I have the following, the only problem is it doesn't work when the number is negative, it always rounds down rather than to zero. I know there should be bitwise if statement that if x is negative then add 15. But I dont know how to implement it, any help is appreciated.
int ezThreeSixteenths(int x) {
int times_two = x << 1;
int times_three = times_two + x;
int divide_eight = times_three >> 4;
int a = 0b11111111;
int a1 = a << 8;
int a2 = a << 16;
int a3 = 0b11111 << 24;
int mask = a | a1 | a2 | a3;
int final = divide_eight & mask;
return final;
}
If you have a function that you are satisfied works when it's positive, test the MSB to detect a negative bit, if so take the two's complement (you don't say whether you can use - as well as + but you can use ^ and +), run your function, then take the two's complement again.
Use twos complement to convert a negative number to a positive number. Then when you're done convert the positive number back to a negative one?
So I am revising for an exam and I got stuck in this problem:
2.67 โโ
You are given the task of writing a procedure int_size_is_32() that yields 1
when run on a machine for which an int is 32 bits, and yields 0 otherwise. You are
not allowed to use the sizeof operator. Here is a first attempt:
1 /* The following code does not run properly on some machines */
2 int bad_int_size_is_32() {
3 /* Set most significant bit (msb) of 32-bit machine */
4 int set_msb = 1 << 31;
5 /* Shift past msb of 32-bit word */
6 int beyond_msb = 1 << 32;
7
8 /* set_msb is nonzero when word size >= 32
9 beyond_msb is zero when word size <= 32 */
10 return set_msb && !beyond_msb;
11 }
When compiled and run on a 32-bitSUNSPARC, however, this procedure returns 0. The following compiler message gives us an indication of the problem: warning: left shift count >= width of type
A. In what way does our code fail to comply with the C standard?
B. Modify the code to run properly on any machine for which data type int is
at least 32 bits.
C. Modify the code to run properly on any machine for which data type int is
at least 16 bits.
__________ MY ANSWERS:
A: When we shift by 31 in line 4, we overflow, bec according to the unsigned integer standard, the maximum unsigned integer we can represent is 2^31-1
B: In line 4 1<<30
C: In line 4 1<<14 and in line 6 1<<16
Am I right? And if not why please? Thank you!
__________ Second tentative answer:
B: In line 4 (1<<31)>>1 and in line 6: int beyond_msb = set_msb+1; I think I might be right this time :)
A: When we shift by 31 in line 4, we overflow, bec according to the unsigned integer standard, the maximum unsigned integer we can represent is 2^31-1
The error is on line 6, not line 4. The compiler message explains exactly why: shifting by a number of bits greater than the size of the type is undefined behavior.
B: In line 4 1<<30
C: In line 4 1<<14 and in line 6 1<<16
Both of those changes will cause the error to not appear, but will also make the function give incorrect results. You will need to understand how the function works (and how it doesn't work) before you fix it.
For first thing shifting by 30 will not create any overflow as max you can shift is word size w-1.
So when w = 32 you can shift till 31.
Overflow occurs when you shift it by 32 bits as lsb will now move to 33rd bit which is out of bound.
So the problem is in line 6 not 4.
For B.
0xffffffff + 1
If it is 32 bit then it will result 0 otherwise some nozero no.
There is absolutely no way to test the size of signed types in C at runtime. This is because overflow is undefined behavior; you cannot tell if overflow has happened. If you use unsigned int, you can just count how many types you can double a value that starts at 1 before the result becomes zero.
If you want to do the test at compile-time instead of runtime, this will work:
struct { int x:N; };
where N is replaced by successively larger values. The compiler is required to accept the program as long as N is no larger than the width of int, and reject it with a diagnostic/error when N is larger.
You should be able to comply with the C standard by breaking up the shifts left.
B -
Replace Line 6 with
int beyond_msb = (1 << 31) << 1;
C -
Replace Line 4 with
int set_msb = ((1 << 15) << 15) << 1 ;
Replace Line 6 with
int beyond_msb = ((1 << 15) << 15) << 2;
Also, as an extension to the question the following should satisify both B and C, and keep runtime error safe. Shifting left a bit at a time until it reverts back to all zeroes.
int int_size_is_32() {
//initialise our test integer variable.
int x = 1;
//count for checking purposes
int count = 0;
//keep shifting left 1 bit until we have got pushed the 1-bit off the left of the value type space.
while ( x != 0 ) {
x << 1 //shift left
count++;
}
return (count==31);
}