演習 2-8

無職の間にK&Rを再読。演習問題の解答をさらす。解く順番は適当。

演習 2-8
整数 x の値を右に n ビット回転する関数 rightrot(x, n)を書け


Exercise 2-8
Write a function rightrot(x, n) that returns the value of the integer x rotated to the right by n bit positions.


最下位ビットを1ビットずつ最上位ビットに持っていく。


最下位ビット (LSB: Least Significant Bit) は 0x01 なんで簡単、
最上位ビット (MSB: Most Significant Bit) は ~(~(unsigned)0 >> 1) でとった。
2ビットの場合 0x7FFF という形を作るために 0xFFFF (~0) を 1ビット右シフトするが、
~0 >> 1 だと符号拡張されるので、 ~(unsigned)0 >> 1 としている。


ループを使わずにはできんのかなぁ。

#include <stdio.h>

/* Answer */
unsigned rightrot(unsigned x, int n)
{
  while (n-- > 0) {
    int lsb = x & 0x01;
    x = x >> 1 | ~(~(unsigned)0 >> lsb);
  }
  return x;
}



void showbits(long num, int size);
void _showbits(long num, int remain);


int main(void)
{
  unsigned a = 0x0ACDC987;
  unsigned b;

  showbits(a, sizeof(a));

  b = rightrot(a, 8);

  showbits(b, sizeof(b));
  
  return 0;
}



void showbits(long num, int size)
{
  _showbits(num, size * 2 - 1);
  putchar('\n');
}


void _showbits(long num, int remain)
{
  static const char bitpattern[16][5] = {
    "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
    "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111",
  };
 
  if (remain > 0) {
    _showbits(num >> 4, remain - 1);
    putchar(',');
  }
  
  printf("%s", bitpattern[ num & 0x0F ]);
}