In short, no.
Bit operators do not make sense with double or float , and the standard says that bit operators ( ~ , & , | , ^ , >> , << ) and assignment options) do not accept double or float operands.
Both double and float have 3 sections - sign bit, exponent and mantissa. Suppose for a moment that you could shift double to the right. The exponent, in particular, means that there is no simple translation to shift the bit pattern to the right - the sign bit will move to the exponent, and the least significant bit of the exponent will move to the mantissa with completely non-obvious sets of values. IEEE 754 implies 1 bit before the actual mantissa bits, which also complicates the interpretation.
Similar comments apply to any of the other bitwise operators.
Thus, since there is no robust or useful interpretation of bitwise operators for double values, they are not allowed by the standard.
From the comments:
I'm only interested in binary representation. I just want to print it, and not do anything useful with it.
This code was written several years ago for the SPARC (big-endian) architecture.
#include <stdio.h> union u_double { double dbl; char data[sizeof(double)]; }; union u_float { float flt; char data[sizeof(float)]; }; static void dump_float(union u_float f) { int exp; long mant; printf("32-bit float: sign: %d, ", (f.data[0] & 0x80) >> 7); exp = ((f.data[0] & 0x7F) << 1) | ((f.data[1] & 0x80) >> 7); printf("expt: %4d (unbiassed %5d), ", exp, exp - 127); mant = ((((f.data[1] & 0x7F) << 8) | (f.data[2] & 0xFF)) << 8) | (f.data[3] & 0xFF); printf("mant: %16ld (0x%06lX)\n", mant, mant); } static void dump_double(union u_double d) { int exp; long long mant; printf("64-bit float: sign: %d, ", (d.data[0] & 0x80) >> 7); exp = ((d.data[0] & 0x7F) << 4) | ((d.data[1] & 0xF0) >> 4); printf("expt: %4d (unbiassed %5d), ", exp, exp - 1023); mant = ((((d.data[1] & 0x0F) << 8) | (d.data[2] & 0xFF)) << 8) | (d.data[3] & 0xFF); mant = (mant << 32) | ((((((d.data[4] & 0xFF) << 8) | (d.data[5] & 0xFF)) << 8) | (d.data[6] & 0xFF)) << 8) | (d.data[7] & 0xFF); printf("mant: %16lld (0x%013llX)\n", mant, mant); } static void print_value(double v) { union u_double d; union u_float f; f.flt = v; d.dbl = v; printf("SPARC: float/double of %g\n", v); // image_print(stdout, 0, f.data, sizeof(f.data)); // image_print(stdout, 0, d.data, sizeof(d.data)); dump_float(f); dump_double(d); } int main(void) { print_value(+1.0); print_value(+2.0); print_value(+3.0); print_value( 0.0); print_value(-3.0); print_value(+3.1415926535897932); print_value(+1e126); return(0); }
The commented out function 'image_print ()' prints a random set of bytes in hexadecimal with various minor changes. Contact me if you want to receive a code (see my profile).
If you are using Intel (little-endian), you probably need to tweak the code to deal with the reverse bit order. But this shows how you can do this - using union .