vvn*_*man 4 c c++ optimization bit-manipulation
我想约束signed short
0到4095之间变量的值,之后我将最重要的8位作为我的最终值用于其他地方.现在我正在以基本的方式做到,如下所示:
short color = /* some external source */;
/*
* I get the color value as a 16 bit signed integer from an
* external source I cannot trust. 16 bits are being used here
* for higher precision.
*/
if ( color < 0 ) {
color = 0;
}
else if ( color > 4095 ) {
color = 4095;
}
unsigned char color8bit = 0xFF & (color >> 4);
/*
* color8bit is my final value which I would actually use
* in my application.
*/
Run Code Online (Sandbox Code Playgroud)
有没有办法只使用位操作,即不使用任何条件?这可能有助于加快速度,因为此操作在代码中发生了数千次.
以下内容无效,因为它不会处理负值和溢出等边缘情况:
unsigned char color8bit = 0xFF & (( 0x0FFF & color ) >> 4 );
Run Code Online (Sandbox Code Playgroud)
编辑: 亚当罗森菲尔德的答案是采取正确的方法,但错误实施的答案.ouah的答案给出了正确的结果,但采取了我原本打算找出的不同方法.
这是我最终使用的:
const static short min = 0;
const static short max = 4095;
color = min ^ (( min ^ color ) & -( min < color ));
color = max ^ (( color ^ max ) & -( color < max ));
unsigned char color8bit = 0xFF & (( 0x0FFF & color ) >> 4 );
Run Code Online (Sandbox Code Playgroud)
是的,看到这些令人讨厌的黑客攻击:
short color = ...;
color = color ^ (color & -(color < 0)); // color = max(color, 0)
color = 4096 ^ ((color ^ 4096) & -(color < 4096)); // color = min(color, 4096)
unsigned char color8bit = 0xFF & (color >> 4);
Run Code Online (Sandbox Code Playgroud)
这实际上是否真的更快,我不知道 - 你应该剖析.目前大多数现代x86和x86-64芯片都支持"条件移动"指令(cmov),它有条件地存储取决于EFLAGS状态位的值,优化编译器通常会从三元表达式生成这些指令color >= 0 ? color : 0
.这些可能会最快,但它们不会在较旧的x86芯片上运行.
您可以执行以下操作:
BYTE data[0x10000] = { ..... };
BYTE byte_color = data[(unsiged short)short_color];
Run Code Online (Sandbox Code Playgroud)
在你的日子里,64kb表并不是一件令人发指的事情,可能是可以接受的.与其他可能的方法相比,此代码变体中的汇编程序命令数量绝对最小.