#include <stdio.h>
#include <stdlib.h>
/*
Handles edge cases:
- Validates i and j
- Prevents undefined behavior from shifting by ≥ 64 bits
- Masks M so only the required bits are copied
*/
/* Convert unsigned long long to binary string without leading zeros */
void to_binary(unsigned long long x, char *buffer, size_t size) {
if (size == 0) return;
if (x == 0) {
if (size >= 2) {
buffer[0] = '0';
buffer[1] = '\0';
}
return;
}
char temp[70];
int idx = 0;
while (x > 0 && idx < (int)sizeof(temp) - 1) {
temp[idx++] = (x & 1ULL) ? '1' : '0';
x >>= 1;
}
temp[idx] = '\0';
/* Reverse into buffer */
int len = idx;
if ((size_t)len + 1 > size) len = (int)size - 1;
for (int i = 0; i < len; i++)
buffer[i] = temp[len - 1 - i];
buffer[len] = '\0';
}
/* Copy bits from M into N between bit positions [i, j] */
unsigned long long copy_bits(unsigned long long N,
unsigned long long M,
int i, int j)
{
if (i < 0 || j < 0 || i > j || j >= 63) {
fprintf(stderr, "Invalid bit range\n");
exit(1);
}
int length = j - i + 1;
/* Mask for bits i..j */
unsigned long long mask = ((1ULL << length) - 1ULL) << i;
/* Clear bits i..j in N */
unsigned long long N_cleared = N & ~mask;
/* Take only the needed bits from M and shift into place */
unsigned long long M_shifted = (M & ((1ULL << length) - 1ULL)) << i;
return N_cleared | M_shifted;
}
int main(void) {
/*
N: 100 011111 00
M: 110011
Result: 100 110011 00
*/
unsigned long long N = 0b10001111100ULL;
unsigned long long M = 0b110011ULL;
int i = 2;
int j = 7;
unsigned long long result = copy_bits(N, M, i, j);
char bufN[70], bufM[70], bufR[70];
to_binary(N, bufN, sizeof(bufN));
to_binary(M, bufM, sizeof(bufM));
to_binary(result, bufR, sizeof(bufR));
printf("N: %s\n", bufN);
printf("M: %s\n", bufM);
printf("Result: %s\n", bufR);
return 0;
}
/*
OUTPUT:
N: 10001111100
M: 110011
Result: 10011001100
*/