如何以更优化的方式提取一点?

时间:2009-10-04 12:31:04

标签: c optimization

我今天接受了采访,他们要求我写两个“C”函数,一个用于提取单个位,另一个用于从字符中提取一系列位。我花了一段时间想出了这些方法。

int extractBit(char byte, int pos) {
    assert( (pos >= 0) && (pos < 8) );
    return ( ( byte & (1<<pos) ) >> pos);
}
char extractBitRange(char byte, int startingPos, int offset) {
   assert( ( (startingPos + offset) >= 0) && ( (startingPos + offset) < 8) );
   return ( byte >> startingPos ) & ~(0xff << (offset + 1));
}

但是面试官一直在问我是否可以进一步加快代码(就cpu周期而言)以及是否有任何优化范围可以实现它。 我显然不合适,我很想知道你会怎么做?

6 个答案:

答案 0 :(得分:18)

在extractBit中,如果您先移动,则可以使用1而不是(1<<pos)进行屏蔽。 考虑到pos是函数的参数,可以节省计算量。

return (byte >> pos) & 1;

在第二个函数中,我断言startingPosoffset都是正数而不是断言它们的和是正数,这样就更有道理了。

答案 1 :(得分:5)

查找表?

答案 2 :(得分:3)

你在比特范围内做的另一个:


~(0xff << (offset + 1))
-->
~(0xfe << offset)

因为<< 1不过是*2,你可以对你的常量进行这个操作(如果你在单元字节上操作就是摆脱LSB)。

答案 3 :(得分:3)

您可以通过先向右移动然后屏蔽该位来加速第一个功能:

int extractBit(char byte, int pos) {
   return (byte >> pos) & 0x01;
}

这可以节省您一次操作。

对于第二个问题,我假设startingPos是要提取的块的第一位,offset是您需要的块中的位数。 然后你可以用这个:

char extractBitRange(char byte, int startingPos, int offset) {
   return (byte >> startingPos) & ((1 << offset)-1);
}

当然,您必须小心范围,就像在代码中一样。

编辑:如果您希望extractBitRange(b,i,0)表现得像extractBit(b,i)并在位置i处提取一个位,则此变体会执行此操作:

return (byte >> startingPos) & ((2 << offset) - 1);

答案 4 :(得分:0)

int extractBit(int byte, int pos) 
{
    if( !((pos >= 0) && (pos < 16)) )
    {
        return 0;
    }
    return ( ( byte & (1<<pos) ) >> pos);
}
int _tmain()
{
    // TODO: Please replace the sample code below with your own.

    int value;
    signed int res,bit;
    value = 0x1155;
    printf("%x\n",value);
    //Console::WriteLine("Hello World");
    //fun1();
    for(bit=15;bit>=0;bit--)
    {
        res =extractBit(value,bit);
        printf("%d",res);
    }
    return 0;
}

答案 5 :(得分:-3)

如果您想快速获得,可以使用查找表。我猜这就是面试官的目的(作为“我怎样才能让这更快”的最终答案)。

基本上,这意味着您事先创建了一个巨大的表,将每个可能的参数组合映射到正确的结果。例如,你有:

byte = 0x0, pos = 0, result = 0
byte = 0x0, pos = 1, result = 0
...
byte = 0x1, pos = 0, result = 1

显然,这需要放入有效的c数据结构(数组,由byte和pos索引)。这将允许您在函数中根据您选择的索引方案返回数组中的位置。

对于第一个函数,这不会占用太多内存。我们讨论的是一个字节的值(一个字节可以有256个不同的值)乘以8个可能的值来启动pos,这使得一个2048的数组。

对于第二个功能,这实际上会占用更多空间。你需要将起始和结束pos的所有可能值乘以256倍(请记住,起始和结束pos都有非法组合)。

我猜测面试官只是想让你回答这将是一种加快速度的方法,然后提供上述想法,试图估计它会花费多少空间与节省的时间。