u/cryptofakir

Weird shift expression result

This code outputs what I believe are the wrong results in 3 of the 4 cases. I think the upper 8 bits of the uint16_t should be always 0, because the shifts should occur on uint8_t and only the result should be cast to (uint16_t).

Why am I wrong?

/* Compile: gcc sol.c main.c -o prog && ./prog <1-4> */
#include <stdio.h>
#include <stdint.h>

/* byte:    An 8-bit input
   returns: An 8-bit value (returned as uint16_t) where the high 4 bits
            and low 4 bits of byte are swapped
   Example: swap_nibbles(0xF0) returns 0x0F
*/
uint16_t swap_nibbles(uint8_t byte) {
    return (uint16_t)((byte << 4) | (byte >> 4));
}


void test1(void) {
    uint8_t b = 0xF0;
    uint16_t r = swap_nibbles(b);
    printf("Result: 0x%04X\n", r);
}

void test2(void) {
    uint8_t b = 0xA2;
    uint16_t r = swap_nibbles(b);
    printf("Result: 0x%04X\n", r);
}

void test3(void) {
    uint8_t b = 0x00;
    uint16_t r = swap_nibbles(b);
    printf("Result: 0x%04X\n", r);
}

void test4(void) {
    uint8_t b = 0xFF;
    uint16_t r = swap_nibbles(b);
    printf("Result: 0x%04X\n", r);
}

int main(int argc, char **argv) {
    if (argc < 2) {
        printf("Usage: %s <1-4>\n", argv[0]);
        return 1;
    }
    int t = argv[1][0] - '0';
    switch (t) {
        case 1: test1(); break;
        case 2: test2(); break;
        case 3: test3(); break;
        case 4: test4(); break;
        default: printf("Invalid test. Use 1-4.\n"); return 1;
    }
    return 0;
}

outputs

❯ ./main 1
Result: 0x0F0F
❯ ./main 2
Result: 0x0A2A
❯ ./main 3
Result: 0x0000
❯ ./main 4
Result: 0x0FFF
reddit.com
u/cryptofakir — 6 days ago