13.2.6 计算绝对值的宏
上一节介绍的代码已经很高效了,但有一个问题,那就是函数框架。只要使用返回double类型的函数形式就必然有函数调用操作和浮点数据寄存器的装载和清空等工作。所以,高效的代码应该使用宏的形式。这些宏均通过直接设置浮点数的符号位得到绝对值,没有使用任何浮点指令。
对于double类型,计算绝对值的宏是:
- #define USEABS double __abstd
- #define myabs(x) (__abstd=x, \
- *(unsigned __int64*)&__abstd&=
- 0x7FFFFFFFFFFFFFFF, __abstd )
引入临时变量是因为x可能是一个表达式,无法进行地址计算,而此处的double和__int64的类型转换不是值转换,需要通过指针作间接转换,需要可以取地址的类型。使用举例:
- USEABS;
- double a = -0.5;
- double xa = myabs( a );
这个宏的调用y = myabs( x )最终生成的代码只有整型指令。类似的,对于float类型有:
- #define USEABS float __abstf
- #define myabs(x) (__abstf=x, \
- *(unsigned __int64*)&__abstf&=
- 0x7FFFFFFFFFFFFFFF, __abstf )
如果允许改变变量,即将自身转换成自身的绝对值,类似x=myabs(x),那么对于double类型还可以使用:
- #define myabs( x ) __asm and byte ptr x[7], 0x7F
这条语句直接修改浮点数的符号位。
例如:
- double x = -1.0999;
- myabs( x )
- printf( "%E\n", x );
结果是1.099900E+000。
只是这个宏实际上是嵌入式汇编,使用时必须非常小心。类似的,对于float类型有:
- #define myabs( x ) __asm and byte ptr x[3], 0x7F
【责任编辑:
董书 TEL:(010)68476606】