我在为1byte / 8位校验和编写算法时遇到问题。 显然,对于十进制值为255的8位,最重要的位必须环绕。我想我正确地做到了。
这是代码......
#include <stdio.h>
int main(void)
{
int check_sum = 0; //checksum
int lcheck_sum = 0; //left checksum bits
int rcheck_sum = 0; //right checksum bits
short int mask = 0x00FF; // 16 bit mask
//Create the frame - sequence number (S) and checksum 1 byte
int c;
//calculate the checksum
for (c = 0; c < length; c++)
{
check_sum = (int)buf[c] + check_sum;
printf("\n Check Sum %d ", check_sum); //debug
}
printf("\nfinal Check Sum %d", check_sum); //debug
//Take checksum and make it a 8 bit checksum
if (check_sum > 255) //if greater than 8 bits then encode bits
{
lcheck_sum = check_sum;
lcheck_sum >> 8; //shift 8 bits to the right
rcheck_sum = check_sum & mask;
check_sum = lcheck_sum + rcheck_sum;
}
//Take the complement
check_sum = ~check_sum;
//Truncate - to get rid of the 8 bits to the right and keep the 8 LSB's
check_sum = check_sum & mask;
printf("\nTruncated and complemented final Check Sum %d\n",check_sum);
return 0;
}
答案 0 :(得分:3)
简短的回答:你没有正确地做到这一点,即使如果算法将如你的代码所暗示的那样(这是不太可能的)。
标准警告:如果您的变量可能换行(未定义的行为),或者您想要右移可能的负值,请不要使用int
(实施定义)。 OTOH,对于无符号类型,包裹和移位行为由标准明确定义。
进一步说明:如果您需要特定的比特大小,请使用stdint.h
类型!内置的标准类型不保证(包括char
)来提供此类。
通常,8位缓冲区的8位校验和计算如下:
#include <stdint.h>
uint8_t chksum8(const unsigned char *buff, size_t len)
{
unsigned int sum; // nothing gained in using smaller types!
for ( sum = 0 ; len != 0 ; len-- )
sum += *(buff++); // parenthesis not required!
return (uint8_t)sum;
}
目前尚不清楚你所做的所有类型转换或转变; uint8_t
保证最小(无符号)类型,高位保证&#34;切断&#34;。
只需将此代码与您的代码进行比较,您就应该能够看到代码是否有效。
另请注意,没有 单校验和算法。我没有在我的代码中反转结果,也没有像你那样折叠上下字节(后者非常罕见,因为它不会增加更多的保护)。
因此,您必须验证要使用的算法。如果确实需要折叠16位结果的两个字节,请将sum
更改为uint16_t`并按如下方式折叠字节:
uint16_t sum;
...
// replace return with:
while ( sum > 0xFFU )
sum = (sum & 0xFFU) + ((sum >> 8) & 0xFFU);
return sum;
这关心添加两个字节sum的任何溢出(循环也可以展开,因为溢出只能发生一次)。
有时,CRC算法被称为&#34;校验和&#34;,但这些实际上是一个非常不同的野兽(数学上,它们是二进制多项式除法的余数)并且需要更多处理(在运行时) ,或生成查找表)。 OTOH,CRC提供更多更好的数据损坏检测 - 但不操纵。