Understanding a program in C - c

# include <stdio.h>
int main()
{
int n, c, k;
printf("Enter an integer in decimal number system\n");
scanf("%d", &n);
printf("%d in binary number system is:\n", n);
for (c = 31; c >= 0; c--)
{
k = n >> c;
if (k & 1)
printf("1");
else
printf ("0");
}
printf("\n");
return 0;
}
Can someone help me understand how does this code work? I found this in an online site. It gives the binary counterpart of the number when the decimal is entered. But I don't understand how it is working. And also what does the symbol n>>c mean? Sorry if this is too silly, I am just a beginner in C. Please help me if you can. Thanks a lot.

Okay:
We declare some integers for use later in the program.
int n, c, k;
We get an input number from the user. printf() will print the string to the screen, and scanf() will request data from the user and store it in n.
printf("Enter an integer in decimal number system\n");
scanf("%d", &n);
We now print back to the user the value of n
printf("%d in binary number system is:\n", n);
This is a for loop. It has three parts. The first part gets run before we enter the loop, but only on the first iteration of the loop. So we set c to 31. Then, we check the condition. Is c >= 0? Yes. It is.
We can ignore the last part for now.
for (c = 31; c >= 0; c--)
{
This assigns to k the value of n shifted to the right c times. This is similar to dividing a number by 2 and then removing any decimals. So 5 >> 2 == 1. And 7 >> 1 == 3. Many calculator programs have this button as well.
This iteration, we have n as whatever the user input (Let's say 52). and c is 31. So this would have a value of 0 this loop.
k = n >> c;
Now, this test functions as an even or odd test. If it is odd, we print 1, and 0 otherwise. This also can be seen as looking at the bottom bit of a number and choosing if it is 1 or 0.
if (k & 1)
printf("1");
else
printf ("0");
We now finish this block of code, and we go back to the for loop. Now, on following iterations, we will execute the third block of code (the --c). So c == 30. Then, we will run the middle section, and verify that we still meet the conditions to execute this loop.
}
I imagine the remainder of the program is not interesting.
printf("\n");
return 0;
}
Now, what does this code actually do?
So this code as a whole attempts to print the binary representation of a number. It assumes a few things, including that the number fits in an integer, and the system's integers are 32 bits.
More generally, in each loop of the for loop, we grab the last bit of the number that we haven't seen yet, and print 1 if that bit is high.
If you don't know binary notation yet, then that is something that you really need to learn to have this code make any sense.

The statement
k = n >> c;
right shift n to c bits. The expression k & 1 in if returns 1 if the last bit of k is 1 else it returns 0. Taking n = 8 and c = 7, see the example (assuming 8 bit representation):
iteration print
--------- -----
1. k = 0000 1000 >> 7 = 0000 0000
0000 0000 & 0000 0001 = 0000 0000 = 0 ==> 0
2. k = 0000 1000 >> 6 = 0000 0000
0000 0000 & 0000 0001 = 0000 0000 = 0 ==> 0
3. k = 0000 1000 >> 5 = 0000 0000
0000 0000 & 0000 0001 = 0000 0000 = 0 ==> 0
4. k = 0000 1000 >> 4 = 0000 0000
0000 0000 & 0000 0001 = 0000 0000 = 0 ==> 0
5. k = 0000 1000 >> 3 = 0000 0001
0000 0001 & 0000 0001 = 0000 0000 = 0 ==> 1
. ..
. ..
8. k = 0000 1000 >> 0 = 0000 0000
0000 0000 & 0000 0001 = 0000 0000 = 0 ==> 0

Related

Bitshift (rotation) with hexadecimal in C [duplicate]

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.

How to return middle bits?

I searched online and the common solution for returning x bits from start seems to be:
mask = ((1 << x) - 1 ) << start
then, mask & value.
However, I'm confused on how this works still.
If I have a number 0101 1100 and I want to return the two bits from positions 5 and 6 (11)
mask = ((1<<2)-1) << 5
1<<2 = 0000 0100, and subtracting 1 yields 0000 0011 then, shifting 5 is 0110 0000
If I take 0110 0000 & 0101 1100 (the original), I get 0100 0000
This is not the answer I want, so what am I doing wrong?
Assuming we're referring to two's complement binary, then 11 would be bits 2 and 3 (or 3 and 4, depending on who you ask).
Think of it this way. If you want to get a specific amount of bits from the middle of a binary value, then you can first shift it to the right n times where n is the index of the first bit of interest.
Shifting 0101 1100 to the right twice yields 0001 0111
Here, we're interested in the first two bits, so we can simply call 0001 0111 & 3 because 3 = 00000011.
Therefore, the formula for this specific example is (b >> 2) & 3 where b is the binary value.
If you want the value at their current location, you can call 0101 1100 & 12 because 12 = 00001100, which returns 0000 1100.
Bit positions are typically counted from least- to most-significant, i.e. right-to-left.
0101 1110
---- ----
7654 3210
The bits you want are bits 2 and 3.
for e.g input num is 92 = 0101 1100
initial pos = 1
ending pos = 4
Now your task is to find the number b/w 1st and 4th position(LSB to MSB), output should be 11 means 3.
First find the no of ones b/w these 2 positions, for this rotate loop from starting position to ending position and do
sum = sum | 1<<i; // sum =12( 1100)
Next if you do sum & num, you will get output b/w given positions which is 1100 but you need 11 so do 1100 >> 2(which is n1+1)
Here is the my solution
int sum = 0,num,res; /** num is your input number **/
for(int i=n1+1;i<n2;i++) /* n1 is starting position and n2 is the ending position */
sum = sum | (1<<i); //counting ones
res = sum & num; // we will get o/p in middle
res = res>>(n1+1); // shift previous res to correct position
Finally prints the res.
As advised by many, you should start your positioning from the right.
num = 0101 1100
Positions: 8765 4321
Then the given solution work's just fine.
However, a more detailed approach by myself would be:
To get the values of the bits at position 3 and 4 ('11'), I would do the following:
Let's say you want the bit at position k. Shift a 1, k-1 positions to the left and evaluate it with the &-operator. Shift it back, then save the result in an array with the length of how many bits you want. Repeat the process for the rest.
int mask = 1 << (k - 1);
int bitAtPosK = (num & mask) >> (k - 1);
... do this in a loop and save the results.
Visualisation for Position 3:
num = 0101 1100
1 << 2 results in 0000 0010
and
0101 1100
0000 0100
--------- &
0000 0100
0000 0100 >> 2 results in 1

what does bit_test() function do?

I'm reading Programming in C, 4th edn by Stephen Kochan.
Exercise: Write a function called bit_test() that takes two arguments: an unsigned int and a bit number n. Have the function return 1 if bit number n is on inside the word, and 0 if it is off. Assume that bit number 0 references the leftmost bit inside the integer. Also write a corresponding function called bit_set() that takes two arguments: an unsigned int and a bit number n. Have the function return the result of turning bit n on inside the integer.
This is one of the exercise's answers on their forum.
12-5
-----
/* test bit n in word to see if it is on
assumes words are 32 bits long */
int bit_test (unsigned int word, int n)
{
if ( n < 0 || n > 31 )
return 0;
if ( (word >> (31 - n)) & 0x1 )
return 1;
else
return 0;
}
unsigned int bit_set (unsigned int word, int n)
{
if ( n < 0 || n > 31 )
return 0;
return word | (1 << (31 - n));
}
Now I tried to understand it like this and as per my understanding it always returns 0. What does this function actually do?
It just checks whether a bit is set or not.
It assumes that it unsigned int is stored in 32 bit on that particular system.
Why the check?
Check is needed to make it safe ( I am not shifting a negative value or value greater than 31 ) As first one complains of being an error and the seecond one is useless as it returns 0.
what it really does in (word >> (31 - n)) & 0x1 )?
x x y x x x x x x
0 1 2 3 4 5 6 7 8
|-----------|
8-2=6
(Here I considered 9 bit words instead of 32. In your case it will be 31-3=28
So right shift it 6 bit
0 0 0 0 0 0 x x y
Now how to check if it is set or not?
0 0 0 0 0 0 x x y
& 0 0 0 0 0 0 0 0 1
________________________
0 0 0 0 0 0 0 0 y if it is set it returns 1 else 0
if that bit is et the result will be 1 else 0.
What does bit_set do?
It returns that nth bit set.
So if you input
0001 0010 1
and set bit is 0 (you want to set bit at position 0) then you will get
1001 0010 1
return word | (1 << (31 - n));
let the word be 0001 1001 1
You want to set bit 2 [0 indexing]
0001 1001 1
| 0010 0000 0
0011 1001 1
You have to apply logical or operation on with that value.
How to get that value?
Here we just want this number
0010 0000 0
|-------|
6 shift needed (left shift)
1 << (8-2) ---> is how you get it.
Or in your case 1<<(31-n)
Now I get what you are thinking wrong.....
You considered 25
0000 0000 0000 0000 0000 0000 0000 1101
The bit in 3rd (0 indexing) position is this
000[0] 0000 0000 0000 0000 0000 0000 1101
This bit is unset or 0.
Try 29th position of number 25 you will get 1 as answer.
The problem statement has us identify the leftmost, or highest order bit as n = 0, and the rightmost, or lowest order bit as n = 31.
The bit_test() function shifts the test bit to the lowest order position and does a bitwise AND to find if the test bit was set. For example, to test if the bit n = 0 is set for the bit pattern:
1111 1111 1111 1111 1111 1111 1111 1111
there is a shift to the right (word >> 31 - 0):
0000 0000 0000 0000 0000 0000 0000 0001
then the bitwise AND with 0x1 evaluates to 1, indicating that the n = 0 bit was set.
The bit_set() function shifts a bit-pattern with only the lowest order bit set to the left so that only the bit indicated by n is set, and then combines this bit pattern with the input number using a bitwise OR to set the n bit. If the input number is 0, and n = 3, then the lowest order bit of the bit pattern for 1 (or 0x1):
0000 0000 0000 0000 0000 0000 0000 0001
is shifted to the left (1 << 31 - 3):
0001 0000 0000 0000 0000 0000 0000 0000
and combined with the bit-pattern for 0 using a bitwise OR:
0001 0000 0000 0000 0000 0000 0000 0000
The result is that the n bit of the input number is set to 1.

How can I get the value of the least significant bit in a number?

I'm working on a programming project and one of things I need to do is write a function that returns a mask that marks the value of the least significant 1 bit. Any ideas on how I can determine the value using bitwise operators?
ex:
0000 0000 0000 0000 0000 0000 0110 0000 = 96
What can I do with the # 96 to turn it into:
0000 0000 0000 0000 0000 0000 0010 0000 = 32
I've been slamming my head against the wall for hours trying to figure this out any help would be greatly appreciated!
x &= -x; /* clears all but the lowest bit of x */
A more readable code:
int leastSignificantBit(int number)
{
int index = 0;
while ((~number) & 1) {
number >>= 1;
index++;
}
return 1 << index;
}
To be sure you get the right bit/value:
The value at the least significant bit position = x & 1
The value of the isolated least significant 1 = x & -x
The zero-based index of the isolated least significant 1 = log2(x & -x)
Here's how it looks in JavaScript:
let x = 0b1101000;
console.log(x & 1); // 0 (the farthest-right bit)
console.log(x & -x); // 8 (the farthest-right 1 by itself)
console.log(Math.log2(x & -x); // 3 (the zero-based index of the farthest-right 1)

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