K&R C Exercise 2-6: setbits — Set n Bits at Position p

K&R C Exercise 2-6 — 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.

Approach

K&R numbers bit positions from the right starting at 0, so bit 0 is the least-significant bit. The job is to replace a window of n consecutive bits inside x — the window runs from bit p down to bit p+1-n — with the rightmost n bits of y, without touching any bit outside that window.

The operation takes two steps:

  1. Build a mask of n ones and position it over the target window.
  2. Clear those bits in x using AND with the complement of the positioned mask, then OR in the rightmost n bits of y shifted to the same position.

The key formula:

unsigned mask  = ~(~0U << n);        /* n ones at the low-order positions */
int      shift = p + 1 - n;          /* left edge of the window           */
result = (x & ~(mask << shift)) | ((y & mask) << shift);

Why ~0U and not ~0? In C89/C90, left-shifting a negative signed integer is undefined behaviour. ~0 on most systems is a signed int equal to -1. Using the unsigned literal ~0U keeps the mask arithmetic fully defined regardless of the platform’s word width.

Worked example (8-bit illustration)

x = 0xF0 = 1111 0000
p = 5,  n = 3,  y = 0x05 = 0000 0101

mask           = ~(~0U << 3) = 0000 0111
shift          = 5 + 1 - 3   = 3
mask << shift  = 0000 0111 << 3 = 0011 1000
~(mask << 3)   = 1100 0111        ← clearing mask

x & ~(mask << 3)  = 1111 0000 & 1100 0111 = 1100 0000
y & mask          = 0000 0101 & 0000 0111 = 0000 0101
(y & mask) << 3   = 0000 0101 << 3       = 0010 1000

result = 1100 0000 | 0010 1000 = 1110 1000 = 0xE8

Bits 5–3 of x (which were 110) have been replaced by bits 2–0 of y (101), giving 0xE8. Every other bit of x is unchanged.

C Source Code

/* K&R Exercise 2-6 — setbits
 * Compile: gcc -ansi -Wall ex2-6.c -o ex2-6 */
#include <stdio.h>

unsigned setbits(unsigned x, int p, int n, unsigned y);

int main(void)
{
    printf("setbits(0xF0, 5, 3, 0x05) = 0x%02X\n", setbits(0xF0, 5, 3, 0x05));
    printf("setbits(0xFF, 3, 4, 0x00) = 0x%02X\n", setbits(0xFF, 3, 4, 0x00));
    printf("setbits(0x00, 7, 8, 0xFF) = 0x%02X\n", setbits(0x00, 7, 8, 0xFF));
    return 0;
}

unsigned setbits(unsigned x, int p, int n, unsigned y)
{
    unsigned mask = ~(~0U << n);
    int shift = p + 1 - n;
    return (x & ~(mask << shift)) | ((y & mask) << shift);
}

Compile and Run

gcc -ansi -Wall ex2-6.c -o ex2-6 && ./ex2-6

Sample Output

setbits(0xF0, 5, 3, 0x05) = 0xE8
setbits(0xFF, 3, 4, 0x00) = 0xF0
setbits(0x00, 7, 8, 0xFF) = 0xFF

The first call confirms the worked example. The second call clears all four bits of the window at positions 3–0 inside 0xFF (because y=0x00), turning 11111111 into 11110000 = 0xF0. The third call writes all eight bits of 0xFF into 0x00 starting at bit 7 — covering the entire byte — producing 0xFF.

What This Exercise Teaches

  • Unsigned masks avoid undefined behaviour — always use ~0U when building a mask by shifting, never ~0 on a signed int.
  • Mask construction from first principles~(~0U << n) produces exactly n ones in the low-order positions without any hard-coded constant, which means the code adapts automatically to different word widths.
  • Two-step read-modify-write pattern — clear a field with & ~mask, insert new bits with |. This pattern appears in every device-driver register write and network-protocol field-packing routine.
  • K&R bit-position convention — bit 0 is the rightmost. The window from bit p down to bit p+1-n is consistent with getbits earlier in Chapter 2, so these exercises build on each other.
  • Isolating bits of y before shiftingy & mask strips any high bits of y that would otherwise corrupt bits outside the target window after the left shift.

Set Up Your C Environment

You can compile and run this code on any system with GCC. If you haven’t set up C yet for Chapter 2:

Book: The C Programming Language, 2nd Ed — Kernighan & Ritchie


← Exercise 2-5
 | 
Chapter 2 Solutions
 | 
Exercise 2-7 →

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>