How to copy bits from M into N (numbers) between bit positions i and j (edge‑case‑safe) in C

1 Answer

0 votes
#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

*/

 



answered Mar 29 by avibootz

Related questions

...