演習 2-6

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

演習 2-6
位置 p から始まる n ビットを y の右端の n ビットにセットし、他のビットはそのままにした x を返す関数 setbits(x, p, n, y) を書け


Exercise 2-6
Write a function setbits(x, p, n, y) that returns x with the n bits that begin at position p set to the rightmost n bits of y, leaving the other bits unchanged.


位置 p から始まる n ビットのビットマスクを作るのに全部 1 のビットパターン (&HFFFFFFFF) を左右からビットシフトすればいい(左右から 0 を挿入)と思ったけど、ビット長は決め打ちできないので、左シフトだけでビットマスクを作る。

#include <stdio.h>

/* Answer */
unsigned setbits(unsigned x, int p, int n, unsigned y)
{
  n = (n > p + 1) ? p + 1 : n;
  unsigned mask = ~(~0 << n) << (p - n + 1);
  return (x & ~mask) | (y & mask);
}



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


int main(void)
{
  unsigned short a = 0x5678;
  unsigned short b = 0xABCD;
  unsigned short c;

  showbits(a, sizeof(a));
  showbits(b, sizeof(b));

  c = setbits(a, 11, 8, b);

  showbits(c, sizeof(c));
  
  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 ]);
}