在C中翻转双(或浮点)符号的最快方法是什么?
我想,直接访问符号位是最快的方法,并找到以下内容:
double a = 5.0;
*(__int64*)&a |= 0x8000000000000000;
// a = -5.0
float b = 3.0;
*(int*)&b |= 0x80000000;
// b = -3.0
但是,上述内容不适用于负数:
double a = -5.0;
*(__int64*)&a |= 0x8000000000000000;
// a = -5.0
答案 0 :(得分:40)
如果您只是在前置一个否定运算符,即-a
,那么任何体面的编译器都会实现这种位操作。无论如何,你正在努力。你应该对它进行异或。这就是我测试它的编译器所做的事情(GCC,MSVC,CLang)。所以,请帮自己一个忙,写下-a
编辑:请注意C不强制执行任何特定的浮点格式,因此对非整数C变量的任何位操作最终都会导致错误的行为。
由于评论而编辑2 :这是GCC为x86_64发出的否定代码
.globl neg
.type neg, @function
neg:
.LFB4:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
movss %xmm0, -4(%rbp)
movss -4(%rbp), %xmm1
movss .LC0(%rip), %xmm0
xorps %xmm1, %xmm0 /* <----- Sign flip using XOR */
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE4:
.size neg, .-neg
应该注意的是,xorps
是针对浮点设计的XOR,可以处理特殊情况。这是SSE指令。
答案 1 :(得分:27)
a=-a
答案 2 :(得分:5)
此代码未定义,因为它违反了严格别名规则。 What is the strict aliasing rule? 为了做到这一点,你必须依靠编译器为你优化它。
答案 3 :(得分:3)
如果你想要可移植方式,只需乘以-1
并让编译器优化它。