Home > OS >  "Bitwise assignment" in C? Assigning a variable's bits to another
"Bitwise assignment" in C? Assigning a variable's bits to another

Time:12-02

Is it possible to do a bitwise assignment in C? (Assigning the bits of a variable to another, assuming for simplicity that the source and the target of assignment have the same number of bits.)

For example, assign the number int 1 (which has bits 0...01) to a float variable, obtaining not the float number 1.0f but the number (assuming IEEE-754 representation and assuming a float is 4 bytes as the int) with bits:

0 (sign) 0000'0000 (exponent) 0...01 (mantissa)

which would be a subnormal number (cause the exponent bits are all 0's and the mantissa is not zero), hence representing the number

2^-126 2^-23 (assuming mantissa has 23 bits, then 0..(23 zeroes in total)..1 is 2^-23), that is 2^-149, that is approx. 1.4 10^-45.

NOTE: I'm in the process of learning. I am not trying to do this in a real-life scenario.

CodePudding user response:

You could use a union for that:

int source;
float target;

union Data {
    int i;
    float f;
} data;

source = 42;
data.i = source;
target = data.f; // target should now have the bitwise equivalent of 42.

Be mindful about the sizes of the union members. If they are not equal I think they are padded to the right, but to be sure check with the documentation.

CodePudding user response:

You can access the bits of other types via pointer casting or via unions. There is already another answer about the former, so I'll focus on the union approach.

Union members share the same memory, so you could use bit fields or integer types to access the individual bits, and then view the same bits by using a member of another type. However, note that both accessing the value of another type via a union and bit fields themselves are implementation defined, so this is inherently non-portable. In particular it is not specified how the bits end up being aligned in relation to other union members…

An example for the case of floats:

#include <stdio.h>

union float_bits {
    float value;
    struct {
        unsigned mantissa:23;
        unsigned exponent:8;
        unsigned sign:1;
    };
    struct {
        unsigned bits:32;
    };
};

static void print_float_bits(union float_bits f) {
    printf("(%c x x) (x) %f\n", f.sign ? '-' : ' ', (unsigned) f.exponent, (unsigned) f.mantissa, (unsigned) f.bits, f.value);
}

int main(void) {
    union float_bits f;

    f.value = 1;
    print_float_bits(f);
    f.sign = 1;
    print_float_bits(f);

    // Largest normal number
    f.sign = 0; f.exponent = 0xFE; f.mantissa = 0x7FFFFF;
    print_float_bits(f);

    // Infinity
    f.exponent = 0xFF; f.mantissa = 0;
    print_float_bits(f);

    return 0;
}

On my x86-64 machine with 32-bit IEEE-754 floats, compiled with clang, outputs:

(  7f 000000) (3f800000) 1.000000
(- 7f 000000) (bf800000) -1.000000
(  fe 7fffff) (7f7fffff) 340282346638528859811704183484516925440.000000
(  ff 000000) (7f800000) inf

Disclaimer: Very much implementation defined behaviour, non-portable and dangerous. Bitfields used for readability of the example. Other alternatives would be to put an array of char or some integer type like uint32_t in the union instead of bitfields, but it's still very much implementation defined behaviour.

  •  Tags:  
  • c bit
  • Related