简而言之,你没有。
位运算符在应用于double 或float 时没有意义,标准规定位运算符(~、&、|、^、>>、 << 和赋值变体)不接受 double 或 float 操作数。
double 和 float 都有 3 个部分 - 符号位、指数和尾数。假设您可以将double 向右移动。尤其是指数,意味着没有简单的转换来向右移动位模式 - 符号位将移入指数,而指数的最低有效位将移入尾数,完全不明显的集合意义。在 IEEE 754 中,实际尾数位前面有一个隐含的 1 位,这也使解释复杂化。
类似的 cmets 适用于任何其他位运算符。
因此,由于对double 值的位运算符没有合理或有用的解释,因此标准不允许它们。
来自cmets:
我只对二进制表示感兴趣。我只想打印它,不做任何有用的事情。
这段代码是几年前为 SPARC(大端)架构编写的。
#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);
}
注释掉的“image_print()”函数以十六进制打印任意字节集,并进行了各种细微调整。如果您需要代码,请与我联系(请参阅我的个人资料)。
如果您使用的是 Intel(小端),您可能需要调整代码以处理反向位顺序。但它显示了您如何做到这一点 - 使用 union。