K&R Exercise 2-6 : Inserting part of a bitset into another
Avoid UB

Shifting a 1 into the sign position is undefined behavior (UB). (C11 §6.5.7 4)  Instead, use unsigned types.  0 is an int constant.  0u is an unsigned constant.

// return ((~(~0 &lt;&lt; n) &amp; y) &lt;&lt; p) | ((~(~(~0 &lt;&lt; n) &lt;&lt; p)) &amp; x);
return ((~(~0u &lt;&lt; n) &amp; y) &lt;&lt; p) | ((~(~(~0u &lt;&lt; n) &lt;&lt; p)) &amp; x);


Clarity

Code for clarity and let the compiler form optimal code.

// return ((~(~0u &lt;&lt; n) &amp; y) &lt;&lt; p) | ((~(~(~0u &lt;&lt; n) &lt;&lt; p)) &amp; x);
unsigned new_mask = ~(~0u &lt;&lt; n);
unsigned old_mask = ~(mask &lt;&lt; p);
return ((new_mask &amp; y) &lt;&lt; p) | (old_mask &amp; x);


Specifier matching

"%d" with unsigned should have raised a compiler warning/note.  Enable all compiler warnings to avoid such easy to identify problems.

// printf("%d\n", setbits(100, 4, 3, 5));
printf("%u\n", setbits(100, 4, 3, 5));


For this task, using "%4x" would be more informative than "%u".

Wider testing

"I've tested with a number of different scenarios, and this code has passed all of them.". --> Testing with UINT_MAX, UINT_MAX-1, 1, 0 would help check out the "corners" of the function.

Document restrictions

Code limited to 0 &lt;= p &lt; bit_width and 0 &lt;= n &lt; bit_width.  Since code cannot handle all possible input values, stating  restrictions lessens incorrect usage.  

Defining behavior for all possible inputs has the advantage of not needing to list limitations, yet may not be functional needed (and code over-kill).  

Still good to post limitations.

On this last point, perhaps a slight code re-write is in order as one could easily expect n == bit_width to be valid.

// This assumes no padding in `unsigned`
#define UINT_BIT_WIDTH (CHAR_BIT * sizeof(unsigned))

unsigned setbits(unsigned x, int p, int n, unsigned y) {
  unsigned new_mask = n &gt;= UINT_BIT_WIDTH ? UINT_MAX : ~(~0u &lt;&lt; n);
  ...
}