fabs()的实现如何工作?

时间:2013-08-20 05:29:48

标签: c floating-point

用于查找超过here的浮点数的绝对值的算法。 这是如何工作的?

//find absolute value
double x;
*(((int *) &x) + 1) &= 0x7fffffff;

我不明白为什么需要1的偏移量。它说:

  

IA32 64位符号位为0x80000000,int地址偏移量为+1。

有人可以打破这个并解释一下吗?

3 个答案:

答案 0 :(得分:8)

代码在技术上是无效的C,因为它打破了严格的别名规则。但是,如果您告诉编译器不要滥用别名规则,并且保证doubleint在内存中布局为x86:

(int *)&x是指向x的指针。添加1会将指针向前移动4个字节。取消引用它会为您提供double的第4到第7个字节。你掩盖了高位,因为这是double的最后一个字节。

顺便提一下,你可以使用char *并添加7而不是1来阻止它成为别名冲突。它仍然非常不可移植。

答案 1 :(得分:7)

double宽度为8个字节,格式如下:

enter image description here

您显示的代码假定int宽4个字节,intdouble都是little-endian(意味着0-7位存储在字节0中) ,字节1中的位8-15,依此类推。)

如果x是指向double的指针:

*(((int *) &x) + 0) addresses bits 0 through 31;
*(((int *) &x) + 1) addresses bits 32 through 63.

因此,*(((int *) &x) + 1) &= 0x7fffffff将第63位设置为零,将x更改为其绝对值。

答案 2 :(得分:1)

这是高度依赖平台的。

无论如何,你有一个双倍位置,其中最高位是符号位。

如果你的double有8个字节而你的int有4个字节,并且你在LE系统上,那么最高位是最后一个字节的最高位,或者是第二个整数的最高位。

所以你取第二个整数(你也可以写((int *)&x)[1] &= 0x7fffffff)并清除它的最高位。