一个关于CRC的怪事

zhouqingprsc 2010-03-18 07:14:13
一下是一个CCITT的CRC校验的代码。多项式是1021。寄存器初始值是0xFFFF。

unsigned short cal_crc(unsigned char *ptr, unsigned char len)
{
unsigned char i;
unsigned short crc = 0xFFFF;
while(len--)
{
for(i = 0x80; i != 0; i >>= 1)
{
if(crc & 0x8000)
{
crc <<= 1;
crc ^= 0x1021;
}
else
{
crc <<= 1;
}
if((*ptr & i) != 0)
{
crc ^= 0x1021;
}
}
ptr++;
}
return(crc);
}


我发现在中间一个判断中不管是不是都要执行一句crc <<= 1;。我就把这句提出来。代码变成了下面的样子:

unsigned short cal_crc(unsigned char *ptr, unsigned char len)
{
unsigned char i;
unsigned short crc = 0xFFFF;
while(len--)
{
for(i = 0x80; i != 0; i >>= 1)
{
crc <<= 1;
if(crc & 0x8000)
{
crc ^= 0x1021;
}
if((*ptr & i) != 0)
{
crc ^= 0x1021;
}
}
ptr++;
}
return(crc);
}


奇怪的是我用这两段程序给0x01010101计算CRC。上面一段程序的结果是0xE654。下面一段程序的结果是0xC70E。
为什么?为什么?为什么?为什么?为什么?为什么?为什么?为什么?
...全文
100 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
unix_zhangbo 2012-06-04
  • 打赏
  • 举报
回复
初始值设为全F的话,这个程序正确吗
tony2278 2011-05-18
  • 打赏
  • 举报
回复
关键是这里会有问题:


crc <<= 1;
if(crc & 0x8000)

tony2278 2011-05-18
  • 打赏
  • 举报
回复
我也看出来啦~
zhouqingprsc 2010-03-18
  • 打赏
  • 举报
回复
我看出来了。晕死。这都没看出来。
zhouqingprsc 2010-03-18
  • 打赏
  • 举报
回复
对于满足crc & 0x8000的情况,我也是先执行crc <<= 1;再执行crc ^= 0x1021;
对于不满足crc & 0x8000的情况我也是执行了一遍crc ^= 0x1021;
有什么不同呢?
qldsrx 2010-03-18
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 alifriend 的回复:]
这时候你应该提到后面,而不是前面
[/Quote]
提到后面也不对,就不能提出来。
让我们看下这种写法:
if(crc & 0x8000)
{
crc ^= 0x1021;
}
crc <<= 1;
if条件不满足的情况,执行效果一样的,但是if条件一旦满足,这里的执行顺序就颠倒了,看出来了没有?
波导终结者 2010-03-18
  • 打赏
  • 举报
回复
这时候你应该提到后面,而不是前面
波导终结者 2010-03-18
  • 打赏
  • 举报
回复
先if再<<1,与
先<<1再if,走的分支可能就不一样了,所以结果当然不一样了

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧