C函数到Python(不同的结果)

时间:2016-09-05 21:01:12

标签: python bit-manipulation lfsr

我正在尝试将这段代码从C语言移植到python。即使代码相同,输出也是不同的。

这是代码的C版本:

int main(void)
{

uint8_t pac[] = {0x033,0x55,0x22,0x65,0x76};
uint8_t len = 5;
uint8_t chan = 0x64;

btLeWhiten(pac, len, chan);

    for(int i = 0;i<=len;i++)
    {
        printf("Whiten %02d \r\n",pac[i]);
     }

   while(1)
   {    

   }

  return 0;
  }



void btLeWhiten(uint8_t* data, uint8_t len, uint8_t whitenCoeff)
{

uint8_t  m;

while(len--){   
    for(m = 1; m; m <<= 1){

        if(whitenCoeff & 0x80){

            whitenCoeff ^= 0x11;
            (*data) ^= m;
        }
        whitenCoeff <<= 1;

    }
    data++;
  }
}

我目前在Python中拥有的是:

def whiten(data, len, whitenCoeff):
    idx = len 
    while(idx > 0):
        m = 0x01
        for i in range(0,8):
            if(whitenCoeff & 0x80):
                whitenCoeff ^= 0x11
                data[len - idx -1 ] ^= m
                whitenCoeff <<= 1 
                m  <<= 0x01

        idx = idx - 1


pac = [0x33,0x55,0x22,0x65,0x76]
len = 5
chan = 0x64

def main():

whiten(pac,5,chan)
print pac


if __name__=="__main__":
    main()

我看到的问题是,whitenCoeff在C片段中始终保持8位,但在每次循环传递中,它在Python中大于8位。

5 个答案:

答案 0 :(得分:1)

在C中,您正在将数据从0写入len-1,但在Python中,您正在将数据从-1写入len-2。从这一行中删除-1:

data[len - idx -1 ] ^= m
像这样

data[len - idx] ^= m

您还需要将此行放在if:

之外
whitenCoeff <<= 1 

答案 1 :(得分:1)

C中的

whitenCoeff <<= 1在一段时间后变为0,因为它是8位数据。

在python中,没有这样的限制,所以你必须写:

whitenCoeff = (whitenCoeff<<1) & 0xFF

掩盖更高的位。

(别忘了检查数组边界上的vz0注释)

此外还有一个缩进问题。

重写的代码,它给出了相同的结果:

def whiten(data, whitenCoeff):
    idx = len(data)
    while(idx > 0):
        m = 0x01
        for i in range(0,8):
            if(whitenCoeff & 0x80):
                whitenCoeff ^= 0x11
                data[-idx] ^= m
            whitenCoeff = (whitenCoeff<<1) & 0xFF
            m  <<= 0x01

        idx = idx - 1


pac = [0x33,0x55,0x22,0x65,0x76]
chan = 0x64

def main():

    whiten(pac,chan)
    print(pac)


if __name__=="__main__":
    main()

稍微偏离主题:请注意,C版本已经存在问题:

for(int i = 0;i<=len;i++)

应该是

for(int i = 0;i<len;i++)

答案 2 :(得分:1)

你还有一些问题。

  1. whitenCoeff <<= 1;位于C代码中的if块之外,但它位于Python代码中的if块内。
  2. data[len - idx -1 ] ^= m没有正确翻译,它可以从C代码向后工作。
  3. 此代码生成与C代码相同的输出:

    def whiten(data, whitenCoeff):
        for index in range(len(data)):
            for i in range(8):
                if (whitenCoeff & 0x80):
                    whitenCoeff ^= 0x11
                    data[index] ^= (1 << i)
    
                whitenCoeff = (whitenCoeff << 1) & 0xff
    
        return data
    
    if __name__=="__main__":
        print whiten([0x33,0x55,0x22,0x65,0x76], 0x64)
    

答案 3 :(得分:0)

我通过使用0xFF和python代码解决了这个问题。这使变量不会超过8位。

答案 4 :(得分:0)

C中的代码似乎无法正常工作,因为它显示的值多于pac中的值。对此进行更正应该会显示5个值而不是6个值。要将逻辑从C复制到Python,编写以下内容是为了复制结果:

#! /usr/bin/env python3
def main():
    pac = bytearray(b'\x33\x55\x22\x65\x76')
    chan = 0x64
    bt_le_whiten(pac, chan)
    print('\n'.join(map('Whiten {:02}'.format, pac)))


def bt_le_whiten(data, whiten_coeff):
    for offset in range(len(data)):
        m = 1
        while m & 0xFF:
            if whiten_coeff & 0x80:
                whiten_coeff ^= 0x11
                data[offset] ^= m
            whiten_coeff <<= 1
            whiten_coeff &= 0xFF
            m <<= 1


if __name__ == '__main__':
    main()

要模拟8位无符号整数,在几个地方使用代码段& 0xFF将数字截断为适当的大小。 bytearray数据类型用于存储pac,因为在这种情况下,这似乎是最合适的存储方法。代码仍需要文档才能正确理解它。