在C中写入8位校验和

时间:2015-07-01 01:12:08

标签: c checksum

我在为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;
}

1 个答案:

答案 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提供更多更好的数据损坏检测 - 但不操纵