1

I have some trouble with a bit-shift program.

The challenge is to write a program which can shift an unsigned int a number of steps to the left. Both integers are given as input by the user. Thus, given two integers (x and y), the bits in x shall be moved y steps to the left, and the bits which are lost on the left side should be moved to the right. Namely, the bits which are lost outside the most significant are placed in the least significant positions.

To solve the challenge, I have made the following attempt:

#include <stdio.h>
#include <utility.h>

unsigned int bitshift(unsigned int a, unsigned int b)
{
    a<<b;
    b>>a;
    return a,b; 
}

int main (void) 
{
    unsigned int x, y;
    
    printf("Enter two integers (smaller than 32) please:\n");
    scanf("%u%u", &x, &y);
    printf("Your integers are %u and %u.\n", x, y);
    printf("In hexadecimal-format, your integers are %08x and %08x.\n", x, y); 
 
    printf("We are now going to perform a bit shift operation\n");
    printf("The result of the bitshift operation is:\n");
    printf("%u and %u\n", bitshift(x,y));
    printf("In hexadecimal: %08x and %08x\n", bitshift(x,y));
    
    while(!KeyHit()); 
    return 0; 
    
}

However, I'm getting an error message when compiling, e.g. "not enough parameters", which I do not understand.

But what I am most wondering is if the bitshift function will do the job?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • The compilation message should include the line number where the compiler had an issue understanding the code. – Pac0 Oct 26 '20 at 15:43
  • You can't return multiple values in C. – Barmar Oct 26 '20 at 15:43
  • 1
    `return a, b;` is equivalent to `return b;`. See https://stackoverflow.com/questions/52550/what-does-the-comma-operator-do – Barmar Oct 26 '20 at 15:44
  • 1
  • What is `KeyHit()`? – i486 Oct 26 '20 at 15:46
  • 1
    The error message is because your format string has two placeholders, but you've only given one value to format. – Barmar Oct 26 '20 at 15:47
  • 2
    BTW: a more appropriate name for your function would be `rotatebits`. – Jabberwocky Oct 26 '20 at 15:47
  • 2
    Why do you think `bitshift()` needs to return two values in the first place? It should just return the shifted value of `a`, it doesn't need to change `b`. – Barmar Oct 26 '20 at 15:47
  • 1
    https://www.geeksforgeeks.org/rotate-bits-of-an-integer/ – Barmar Oct 26 '20 at 16:06
  • If a problem use the terms `x` and `y` it is unwise to rename the variables `a` and `b` in your code. I know it's trivial but it really helps when trying to understand what the code is doing. For example, the problem ask you to shift x by y bits so why do you shift y by x bits after doing that? What do you think you will achieve by shifting y by x bits? – slebetman Oct 26 '20 at 16:28
  • If you get an error message you should copy and paste the full error message instead of describing it in your own words. – Bodo Oct 26 '20 at 16:51
  • Does this answer your question? [What are bitwise shift (bit-shift) operators and how do they work?](https://stackoverflow.com/questions/141525/what-are-bitwise-shift-bit-shift-operators-and-how-do-they-work) – user14063792468 Oct 26 '20 at 17:31

3 Answers3

4

This is a modification of Barmar's (now deleted) solution for function bitshift with improvements suggested in comments.

Unfortunately, C does not have operators to rotate the bits in a value as might be available in the CPU's instruction set. That's why the operation can be done by moving the least significant bits to the left, moving the most significant bits to the right and combining the results.

To calculate the shift width for shifting the most significant bits to the right, the number of bits in the data type must be calculated using sizeof.

Note that a shift width greater than or equal to the number of bits in the value is undefined behavior (UB). That's why the shift width is calculated modulo the number of bits in the value. Additionally a left shift of 0 would result in UB in the right shift.

#include <stdio.h>
// get CHAR_BITS to make code portable for unusual platforms
#include <limits.h>

unsigned int bitshift(unsigned int a, unsigned int b)
{
    // modulo operation to prevent undefined behavior
    b %= sizeof a * CHAR_BIT; // sizeof a * 8 on usual platforms
    // prevent undefined behavior for right shift
    if(b == 0) return a;

    unsigned int upper = a << b;
    // not portable for unusual platforms
    // unsigned int lower = a >> (sizeof a * 8 - b);
    unsigned int lower = a >> (sizeof a * CHAR_BIT - b);
    
    return upper | lower;
}

int main (void) 
{
    unsigned int x, y;
    
    printf("Enter two integers (smaller than 32) please:\n");
    scanf("%u%u", &x, &y);
    printf("Your integers are %u and %u.\n", x, y);
    printf("In hexadecimal-format, your integers are %08x and %08x.\n", x, y); 
 
    printf("We are now going to perform a bit shift operation\n");
    printf("The result of the bitshift operation is:\n");
    printf("%u\n", bitshift(x,y));
    printf("In hexadecimal: %08x\n", bitshift(x,y));
    
    return 0; 
    
}

Example input/output:

Enter two integers (smaller than 32) please:
1234567890 12
Your integers are 1234567890 and 12.
In hexadecimal-format, your integers are 499602d2 and 0000000c.
We are now going to perform a bit shift operation
The result of the bitshift operation is:
1613571225
In hexadecimal: 602d2499
Enter two integers (smaller than 32) please:
246 28
Your integers are 246 and 28.
In hexadecimal-format, your integers are 000000f6 and 0000001c.
We are now going to perform a bit shift operation
The result of the bitshift operation is:
1610612751
In hexadecimal: 6000000f
Bodo
  • 9,287
  • 1
  • 13
  • 29
1

It is enough tho shift right to get the bits which will be shifted out and or it with the value shifted left. To avoid UBs number of bits should be checked.

unsigned rol(unsigned val, unsigned nbits)
{
    if(nbits && nbits < CHAR_BIT * sizeof(val))
    {
        val = (val >> (CHAR_BIT * sizeof(val) - nbits)) | (val << nbits);
    }
    return val;
}
0___________
  • 60,014
  • 4
  • 34
  • 74
0

You actually want to rotate the bits.

// Rotate the bits of a by b to the left and return the result

unsigned int bitshift(unsigned int a, unsigned int b)
{
  for (unsigned int i = 0; i < b; i++)
  {
    unsigned int lowbit = 0;
    if (a & 0x80000000)
      lowbit = 1;

    a <<= 1;
    a |= lowbit;
  }

  return a;
}

This assumes unsigned int is 32 bits. You should be able to adapt it for 64 bits.

Disclaimer:

This is a very naive method though. If you need speed, you should avoid the loop. This can be done but it's more tricky.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115