创建双整数,通过追加两个整数的二进制表示来实现

4
我正在尝试通过附加两个int的二进制表示来创建一个double。这是我现在的代码:
int i = arc4random();
*(&i+1) = arc4random();
double d = *(double*)&i;

我希望双指针也能使用地址 &i+1 处的值,实际上确实如此。当我打印 i*(&i+1) 的二进制表示并将它们与 d 的二进制表示进行比较时,可以发现 d 是通过附加 *(&i+1)i 组成的。所以先出现了 *(&i+1)?为什么会这样呢? 编辑:还要看一下 Juan Catalan 和 Mark Segal 的答案,了解使用联合执行我所做的操作的正确方式。

5
不要这样做!通过使用未分配给变量的内存,您正在调用未定义的行为。 - Sami Kuhmonen
3
使用union代替。你仍然可以生成NaN,但不会有内存管理问题。 - Juan Catalan
@JuanCatalan 这是个好主意,我没想到! :) - Rugen Heidbuchel
2
这就是“联合”的全部目的,即在几种不同类型之间共享一个内存块。但是要注意sizeof(int)必须确保它在您的架构中是double大小的一半。 - Juan Catalan
2
双精度浮点数不是两个整数值相连。请阅读 http://en.wikipedia.org/wiki/Double-precision_floating-point_format,该页面讨论了C语言中双精度变量实际使用的格式。 - user3629249
显示剩余4条评论
3个回答

4
使用联合(union)代替。这样仍然可以生成NaN,但不会有内存管理问题。
这正是“联合”存在的全部目的:在多种类型之间共享内存块。
请确保在您的架构中,sizeof(double)等于两倍的sizeof(int)

2
你可以使用联合体来实现,像这样:

typedef union {
    double d;
    struct {
        int a;
        int b;
    } integers;
} double_generator;

int main(void) {
    double_generator g;
    g.integers.a = arc4random();
    g.integers.b = arc4random();

    // g.d is now a "randomly generated double"

    return 0;
}

或者“手动”地,可能不太安全,您可以自己完成这项工作:
int main(void) {
    double d;
    *((int *)&d) = arc4random();
    *(((int *)&d) + 1) = arc4random();
    printf("%f", d);
    return 0;
}

在这两种情况下,您可以像使用“int”或“double”一样访问相同的内存。这可能会生成包括“NaN”或“Infinity”在内的所有可能的“double”值。
但是,此代码假设“sizeof(double)”至少是“sizeof(int)”的两倍。如果不是,则必须引入不同的代码来处理它。

1
当我打印出i和*(&i+1)的二进制表示并将它们与d的二进制表示进行比较时,d是通过附加*(&i+1)和i而构成的。这样*(&i+1)首先出现了?!为什么会这样?
字节的实际顺序取决于底层硬件架构的“字节序”。
对于小端架构:
1) the lowest address byte contains the least significant 8 bits of the total variable  
2) the highest address byte contains the most significant 8 bits of the total variable.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接