Bitshift (rotation) with hexadecimal in C [duplicate] - c

This question already has answers here:
Best practices for circular shift (rotate) operations in C++
(16 answers)
Closed 2 years ago.
I'm trying to rotate hexadecimal numbers in C. The problem I have is that, with each loop. more zeros occur in the number.
Here is my code:
int main (void) {
int hex = 0x1234ABCD;
for(int i=0; i<12;i++,hex <<=4){
printf("0x%04x %d ",hex,hex );
pattern(hex);
}
return 0;
}
I saw some other code on this site which added & 0x0F to the shift, but it is not working for me.
Here are my results with the compiler
0x1234abcd 305441741 0001 0010 0011 0100 1010 1011 1100 1101
0x234abcd0 592100560 0010 0011 0100 1010 1011 1100 1101 0000
0x34abcd00 883674368 0011 0100 1010 1011 1100 1101 0000 0000
0x4abcd000 1253888000 0100 1010 1011 1100 1101 0000 0000 0000
0xabcd0000 -1412628480 1010 1011 1100 1101 0000 0000 0000 0000
Thank you for your help.

There is no operator that does a rotation for you. You need to combine 2 shift operations. Also you should use unsigned values when doing bitshift operations.
int main (void) {
unsigned int hex = 0x1234ABCD;
for(int i=0; i<12;i++) {
printf("0x%04x %d ",hex,hex );
pattern(hex);
unsigned int upper = hex >> (sizeof(hex)*CHAR_BIT - 4);
hex <<= 4;
hex |= upper & 0x0F;
}
return 0;
}

When you use the left-shift (<<) operator on a number, shifting by n bits, then the most significant n bits of that number are lost, and the least significant n bits are filled with zeros (as you have noticed).
So, in order to perform a bitwise rotation, you need to first 'save' those top 4 bits, then put them back (using the | operator after shifting them down to the bottom).
So, assuming a 32-bit int size, something like this:
#include <stdio.h>
int main(void)
{
int hex = 0x1234ABCD;
for (int i = 0; i < 12; i++) {
printf("0x%04x %d ", hex, hex);
pattern(hex);
int save = (hex >> 28) & 0x0F; // Save TOP four bits of "hex" in BOTTOM 4 of "save"
hex <<= 4; // Now shift the bits to the left ...
hex |= save; // ... then put those saved bits in!
}
return 0;
}
Note: We mask the save value with 0x0F after the shift to make sure that all other bits are 0; if we don't do this then, with negative numbers, we are likely to get those other bits filled with 1s.

Related

How to mask out first 2 MSB bytes of a 64-bit number?

I have a 64-bit unsigned integer. Which contains 0s in the first two MSB bytes. How can I mask out that first two MSB bytes?
uint64 value;
value = 0000 0000 0000 0000 0000 1101 1111 1010 1110 1111 1111 1111 0101
0101 1101 1101;
uint48 answer;
answer = 0000 1101 1111 1010 1110 1111 1111 1111 0101
0101 1101 1101;
In the above example, the value is a 64-bit number. I want the answer to contain all the bits other than first 2 bytes. So, that I can pack the answer in a byte array of size 6. How can I achieve this in C?
Mask it with 48 1-bits: 0xffffffffffff
uint64_t value = <something>;
uint48_t answer = src & 0xffffffffffff;
But if you know the 2 MSB are zeroes, you don't need to do any masking, just assign the variables:
uint48_t answer = value;
To store them in a byte array, shift by the appropriate number of bytes and mask with 0xff to get a single byte.
uint8_t bytes[6];
for (int i = 0; i < 6; i++) {
bytes[i] = (value >> (40 - 8 * i)) & 0xff;
}
You can use either the original 64-bit value or the 48-bit value, this works for any size at least 6 bytes.
Make a union with your uint64_t value and an array of Bytes.
typefef union
{
uint8_t ByteArray[8];
uint64_t Value;
}Array64T;
Array64T CompleteValue;
CompleteValue.Value = ...
void *copt6lsb(uint64_t val, void *buff)
{
union{
uint8_t d8[2];
uint16_t d16;
}u16 = {.d8[0] = 0xff};
char *pos = &val;
pos = pos + 2 * (u16.d16 == 0xff00);
memcpy(buff, pos, 6);
return buff;
}
Good thing is that most compilers then the optimization is on will optimize out the union and will replace the comparison with assignment.
https://godbolt.org/z/JKXDC2
and platforms which allow unaligned access will optimize the memcpy as well
https://godbolt.org/z/c3_ypL

C rotate bitfield (explanation needed)

I want to rotate a byte 1 bit to the left. I was looking at several examples from this site and came across this code. Though it works, I'd appreciate any step by step into how does it works.
unsigned int _rotl(const unsigned int value, int shift)
{
if ((shift &= sizeof(value)*8 - 1) == 0) //What does this do?
return value;
return (value << shift) | (value >> (sizeof(value)*8 - shift));
}
First of all, what does the first part does? And for the last part wouldn't shifting by that much you'd pretty much be erasing some of the bits?
For example:
Say
value= 0x50 //01010000
shift = 4
I'll have
for
value << shift
01010000 << 4 => 00000000
And for
value >> (sizeof(value)*8 - shift)
01010000>> (4*8 - 4) => 00000000
So doing the OR operation for both would give me 0. My understanding is wrong obviously, but I'd appreciate anyone 'dumbing' it down for a begginer like me. Thanks.
Let's take it step by step:
unsigned int _rotl(const unsigned int value, int shift)
{
if ((shift &= sizeof(value)*8 - 1) == 0) //What does this do?
return value;
return (value << shift) | (value >> (sizeof(value)*8 - shift));
}
First line:
if ((shift &= sizeof(value)*8 - 1) == 0) //What does this do?
This statement is an optimization and a check rolled into one line. It returns TRUE if one of two conditions is met:
Shift is zero (i.e. don't rotate any bits)
The number of rotations specified by shift would have no effect
That statement returns FALSE otherwise, but also calculates the minimum number of rotations necessary to achieve the desired result, and stores that value in shift. In other words, it calculates shift = shift % size_of_integer_data_type.
For example, if you have a 32-bit integer, then rotating it by 32 bits does nothing. If you rotate it by 64, 96, or any other multiple of 32, that also accomplishes nothing. If the effect of our rotation does nothing then we save ourselves a lot of time and just quit early.
However, we might also specify a lot more work than is necessary. If you have a 32-bit integer, then rotating it by one bit has the same effect as rotating it by 33 bits, or by 65 bits, or 97 bits, etc. This code recognizes this fact, so if you specify shift as 97, it reassigns shift=1 and cuts out the extraneous rotations.
The statement sizeof(value)*8 - 1 returns one less than the number of bits in the representation of value. For example, if sizeof(value) evaluates to 4 (which it will on a system with 32-bit integers), then 4*8 - 1 = 31.
The &= operator is a bitwise-AND with assignment. This means we're doing a bitwise-AND between shift and sizeof(value)*8 - 1 and assigning that result to shift. As before, the right hand side of that expression is equal to the number of bits in value minus one. Thus, this has the effect of masking out all bits of shift that are greater than the size of the representation of value, which in turn has the effect of computing shift = shift % size_of_integer_data_type.
To be concrete, reconsider the 32-bit case. As before, sizeof(value)*8-1 evaluates to 31. Bitwise, this value is 0000 0000 0000 0000 0000 0000 0001 1111. That value is bitwise-ANDed with shift. Any bits in shift's 6th to 32nd positions are set to zero, while the bits in the 1st to 5th positions are unchanged. If you were to specify 97 rotations the result would be one.
0000 0000 0000 0000 0000 0000 0110 0001 (97)
& 0000 0000 0000 0000 0000 0000 0001 1111 (31)
=========================================
0000 0000 0000 0000 0000 0000 0000 0001 (1)
The last thing to do here is to recall that, in C, the return value of an assignment statement is the value that was assigned. Thus, if the new value of shift is zero, then we return immediately, otherwise we continue.
Second line:
return (value << shift) | (value >> (sizeof(value)*8 - shift));
Since C doesn't have a rotation operator (it only has left and right shifts) we have to compute the low-order bits and the high-order bits separately, and then combine them with a bitwise-OR. This line is a simple matter of calculating each side separately.
The statement value << shift calculates the high order bits. It shifts the bit pattern to the left by shift places. The other statement calculates the low order bits by shifting the bit pattern to the right by size_of_integer_type - shift bits. This is easy to see in an example.
Suppose that value has the decimal value 65535 and that shift has the value 26. Then the starting value is:
0000 0000 0000 0000 1111 1111 1111 1111 (65535)
The left shift gives us:
1111 1100 0000 0000 0000 0000 0000 0000 (65535 << 26)
The right shift gives us:
0000 0000 0000 0000 0000 0011 1111 1111 (65535 >> 6)
Then the bitwise-OR combines these results:
1111 1100 0000 0000 0000 0000 0000 0000 (65535 << 26)
| 0000 0000 0000 0000 0000 0011 1111 1111 (65535 >> 6)
=========================================
1111 1100 0000 0000 0000 0011 1111 1111 (65535 rot 26)
You could re-write this code and achieve the same correct result:
unsigned int _rotl(const unsigned int value, int shift)
{
//Assume 8 bits in a byte
unsigned bits_in_integer_type = sizeof(value)*8;
shift = shift % bits_in_integer_type;
if( shift == 0 ) return value; //rotation does nothing
unsigned high_bits = value << shift;
unsigned low_bits = value >> (bits_in_integer_type - shift);
return high_bits | low_bits;
}
unsigned int _rotl(const unsigned int value, int shift)
{
// If all bits in value are zero, do nothing and return
int bitmaskOfAllOnes = sizeof(value)*8 - 1;
if ((shift &= bitmaskOfAllOnes) == 0) //What does this do?
return value;
// Shift value to the left
(value << shift)
// shifting right to handle the wrap around
| (value >> (sizeof(value)*8 - shift));
}
e.g. using 16-bit ints
value = 0x1001
shift = 4
sizeof(value) => 2
//sizeof(value)*8 - 1 => 0xffff
sizeof(value)*8 - 1 => 15 Decimal
shift &= bitmaskOfAllOnes => 0x1001 (i.e. not zero)
value << shift => 0x0010
sizeof(value)*8 - shift => 12
value >> (sizeof(value)*8 - shift) => 0x001
0x0010 | 0x001 => 0x0011

Calculation of Bit wise NOT

How to calculate ~a manually? I am seeing these types of questions very often.
#include <stdio.h>
int main()
{
unsigned int a = 10;
a = ~a;
printf("%d\n", a);
}
The result of the ~ operator is the bitwise complement of its (promoted) operand
C11dr ยง6.5.3.3
When used with unsigned, it is sufficient to mimic ~ with exclusive-or with UINT_MAX which is the same type and value as (unsigned) -1. #EOF
unsigned int a = 10;
// a = ~a;
a ^= -1;
You could XOR it with a bitmask of all 1's.
unsigned int a = 10, mask = 0xFFFFFFFF;
a = a ^ mask;
This is assuming of course that an int is 32 bits. That's why it makes more sense to just use ~.
Just convert the number to binary form, and change '1' by '0' and '0' by '1'.
That is:
10 (decimal)
Converted to binary (32 bits as usual in an int) gives us:
0000 0000 0000 0000 0000 0000 0000 1010
Then apply the ~ operator:
1111 1111 1111 1111 1111 1111 1111 0101
Now you have a number that could be interpreted as an unsigned 32 bit number, or signed one. As you are using %d in your printf and a is an int, signed it is.
To find out the value in decimal from a signed (2-complement) number do as this:
If the most significant bit (the leftmost) is 0, then just convert back the binary number to decimal as usual.
if the most significant bit is 1 (our case here), then change '1' by '0' and '0' by '1', add '1' and convert to decimal prepending a minus sign to the result.
So it is:
1111 1111 1111 1111 1111 1111 1111 0101
^
|
Its most significant bit is 1, so first we change 0 and 1
0000 0000 0000 0000 0000 0000 0000 1010
And then, we add 1
0000 0000 0000 0000 0000 0000 0000 1010
1
---------------------------------------
0000 0000 0000 0000 0000 0000 0000 1011
Take this number and convert back to decimal prepending a minus sign to the result. The converted value is 11. With the minus sign, is -11
This function shows the binary representation of an int and swaps the 0's and 1's:
void not(unsigned int x)
{
int i;
for(i=(sizeof(int)*8)-1; i>=0; i--)
(x&(1u<<i))?putchar('0'):putchar('1');
printf("\n");
}
Source: https://en.wikipedia.org/wiki/Bitwise_operations_in_C#Right_shift_.3E.3E

Sign-extend a number in C

I am having trouble trying to sign-extend a number by extracting part of a bit-string. This has trouble when it is a negative number, it wraps the number around to the positive side.
Here is my code:
// printf("add1 \n");
unsigned short r1 = (instruction>>6)&7;
signed short amount = (instruction& 31); //right here! i am trying to get the last 5 bits and store it in a register but i can't figure out how to make it negative if it is negative
// printf("\namount is %d \n", amount);
unsigned short dest = (instruction>>9)&7;
state->regs[dest] = state->regs[r1]+amount;
setCC(state,state->regs[r1]+amount);
For bit patterns, it's often easier to use hex constants instead of decimal.
signed short amount = (instruction & 0x1F);
Then to sign-extend the number, check the sign-bit (assuming the sign-bit here is the left-most of the 5 extracted bits). If it's set, do a binary inversion and add 1. Take the 2's-complement of the 5-bit value (invert and add one), then take the 2's-complement of the full-width result (invert and add 1).
if (amount & 0x10)
amount = ~(amount^0x1F + 1) + 1;
Eg.
5-bit "bitfield"
X XXXX
0000 0000 0001 1111
0000 0000 0000 0000 invert x ^ 0x1F (= 1 1111)
0000 0000 0000 0001 add 1
1111 1111 1111 1110 invert ~
1111 1111 1111 1111 add 1
0000 0000 0001 0000
0000 0000 0000 1111 invert x ^ 0x1F (= 1 1111)
0000 0000 0001 0000 add 1
1111 1111 1110 1111 invert ~
1111 1111 1111 0000 add 1
Ooops. Even simpler:
-(x^0x1F + 1) Assuming the machine operates with 2's-complement
0000 0000 0001 0110
0000 0000 0000 1001 invert
0000 0000 0000 1010 add 1 (yielding the full-width absolute value)
1111 1111 1111 0110 negate
use bitfields:
union {
int a;
struct {
int a:5;
int b:3;
unsigned int c:20;
} b;
} u = 0xdeadbeef;
int b = u.b.b; // should sign extend the 3-bit bitfield starting from bit 5
Here is how you can sign extend a 5-bit two's complement value portably without tests:
int amount = (instruction & 31) - ((instruction & 16) << 1);
More generally, it the field width is n, non zero and less than the number of bits in an int, you can write:
int amount = (instruction & ~(~1U << (n - 1) << 1)) -
((instruction & (1U << (n - 1)) << 1);
From Hacker's Delight 2-6. Assuming 5 bits of data that must be sign extended (sign bit has value 16).
Best case: If the upper bits are all zeros:
(i ^ 16) - 16
Next best case (as with OP's instruction): If the upper bits contain data that must be discarded:
(i & 15) - (i & 16)
You can check the sign-bit and fix-up the result accordingly:
int width_of_field = 5;
signed short amount = (instruction& 31);
if (amount & (1 << width_of_field >> 1)) // look at the sign bit
{
amount -= 1 << width_of_field; // fix the result
}
Alternatively, use a left-shift followed by a right shift:
width_of_field = 5;
signed short amount = (instruction& 31);
// It is possible to omit the "& 31", because of the left shift below
amount <<= 16 - width_of_field;
amount >>= 16 - width_of_field;
Note: must use two statements to avoid effects of promotion to int (which presumably has 32 bits).

Unexpected C/C++ bitwise shift operators outcome

I think I'm going insane with this.
I have a a piece of code that needs to create an (unsigned) integer with N consequent bits set to 1. To be exact I have a bitmask, and in some situations I'd like to set it to a solid rnage.
I have the following function:
void MaskAddRange(UINT& mask, UINT first, UINT count)
{
mask |= ((1 << count) - 1) << first;
}
In simple words: 1 << count in binary representation is 100...000 (number of zeroes is count), subtracting 1 from such a number gives 011...111, and then we just left-shift it by first.
The above should yield correct result, when the following obvious limitation is met:
first + count <= sizeof(UINT)*8 = 32
Note that it should also work correctly for "extreme" cases.
if count = 0 we have (1 << count) = 1, and hence ((1 << count) - 1) = 0.
if count = 32 we have (1 << count) = 0, since the leading bit overflows, and according to C/C++ rules bitwise shift operators are not cyclic. Then ((1 << count) - 1) = -1 (all bits set).
However, as turned out, for count = 32 the formula doesn't work as expected. As discovered:
UINT n = 32;
UINT x = 1 << n;
// the value of x is 1
Moreover, I'm using MSVC2005 IDE. When I evaluate the above expression in the debugger, the result is 0. However when I step over the above line, x gets value of 1. Lokking via the disassembler we see the following:
mov eax,1
mov ecx,dword ptr [ebp-0Ch] // ecx = n
shl eax,cl // eax <<= LOBYTE(ecx)
mov dword ptr [ebp-18h],eax // n = ecx
There's no magic indeed, compiler just used shl instruction. Then it seems that shl doesn't do what I expected it should do. Either CPU decides to ignore this instruction, or the shift is treated modulo 32, or donno what.
My questions are:
What is the correct behavior of shl/shr instructions?
Is there a CPU flag controlling the bitshift instructions?
Is this according to C/C++ standard?
Thanks in advance
Edit:
Thanks for answers. I've realized that (1) shl/shr indeed treat operand modulo 32 (or & 0x1F) and (2) C/C++ standard treats shift by more than 31 bits as undefined behavior.
Then I have one more question. How can I rewrite my "masking" expression to cover this extreme case too. It should be without branching (if, ?). What'd be the simplest expression?
1U << 32 is undefined behavior in C and in C++ when type unsigned int is 32-bit wide.
(C11, 6.5.7p3) "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"
(C++11, 5.8p1) "The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand."
Shifting by as many or more bits than in the integer type you're shifting is undefined in C and C++. On x86 and x86_64, the shift amount of the shift instructions is indeed treated modulo 32 (or whatever the operand size is). You however cannot rely on this modulo behaviour to be generated by your compiler from C or C++ >>/<< operations unless your compiler explicitly guarantees it in its documentation.
I think the expression 1 << 32 is the same as 1 << 0. IA-32 Instruction Set Reference says that the count operand of shift instructions is masked to 5 bits.
The instruction set reference of IA-32 architectures can be found here.
To fix the "extreme" case, I can only come up with the following code (maybe buggy) that may be a little awkward:
void MaskAddRange(UINT *mask, UINT first, UINT count) {
int count2 = ((count & 0x20) >> 5);
int count1 = count - count2;
*mask |= (((1 << count1) << count2) - 1) << first;
}
The basic idea is to split the shift operation so that each shift count does not exceed 31.
Apparently, the above code assumes that the count is in a range of 0..32, so it is not very robust.
If I have understood the requirements, you want an unsigned int, with the top N bits set?
There are several ways to get the result (I think) you want.
Edit:
I am worried that this isnt very robust, and will fail for n>32:
uint32_t set_top_n(uint32 n)
{
static uint32_t value[33] = { ~0xFFFFFFFF, ~0x7FFFFFFF, ~0x3FFFFFFF, ~0x1FFFFFFF,
~0x0FFFFFFF, ~0x07FFFFFF, ~0x03FFFFFF, ~0x01FFFFFF,
~0x00FFFFFF, ~0x007FFFFF, ~0x003FFFFF, ~0x001FFFFF,
// you get the idea
0xFFFFFFFF
};
return value[n & 0x3f];
}
This should be quite fast as it is only 132 bytes of data.
To make it robust, I'd either extend for all values up to 63, or make it conditional, in which case it can be done with a version of your original bit-masking + the 32 case. I.e.
My 32 cents:
#include <limits.h>
#define INT_BIT (CHAR_BIT * sizeof(int))
unsigned int set_bit_range(unsigned int n, int frm, int cnt)
{
return n | ((~0u >> (INT_BIT - cnt)) << frm);
}
List 1.
A safe version with bogus / semi-circular result could be:
unsigned int set_bit_range(unsigned int n, int f, int c)
{
return n | (~0u >> (c > INT_BIT ? 0 : INT_BIT - c)) << (f % INT_BIT);
}
List 2.
Doing this without branching, or local variables, could be something like;
return n | (~0u >> ((INT_BIT - c) % INT_BIT)) << (f % INT_BIT);
List 3.
List 2 and List 3 This would give "correct" result as long as from is less then INT_BIT and >= 0. I.e.:
./bs 1761 26 810
Setting bits from 26 count 810 in 1761 -- of 32 bits
Trying to set bits out of range, set bits from 26 to 836 in 32 sized range
x = ~0u = 1111 1111 1111 1111 1111 1111 1111 1111
Unsafe version:
x = x >> -778 = 0000 0000 0000 0000 0000 0011 1111 1111
x = x << 26 = 1111 1100 0000 0000 0000 0000 0000 0000
x v1 Result = 1111 1100 0000 0000 0000 0110 1110 0001
Original: 0000 0000 0000 0000 0000 0110 1110 0001
Safe version, branching:
x = x >> 0 = 1111 1111 1111 1111 1111 1111 1111 1111
x = x << 26 = 1111 1100 0000 0000 0000 0000 0000 0000
x v2 Result = 1111 1100 0000 0000 0000 0110 1110 0001
Original: 0000 0000 0000 0000 0000 0110 1110 0001
Safe version, modulo:
x = x >> 22 = 0000 0000 0000 0000 0000 0011 1111 1111
x = x << 26 = 1111 1100 0000 0000 0000 0000 0000 0000
x v3 Result = 1111 1100 0000 0000 0000 0110 1110 0001
Original: 0000 0000 0000 0000 0000 0110 1110 0001
You could avoid the undefined behavior by splitting the shift operation in two steps, the first one by (count - 1) bits and the second one by 1 more bit. Special care is needed in case count is zero, however:
void MaskAddRange(UINT& mask, UINT first, UINT count)
{
if (count == 0) return;
mask |= ((1 << (count - 1) << 1) - 1) << first;
}

Resources