校验和计算 - 所有字节的二进制补码

Ang*_*ber 4 c++ algorithm checksum

我有关于创建如下所述消息的校验和的说明:

校验和由单个字节组成,该字节等于从"消息类型"字一直到消息块结尾的所有字节的二进制补码和(不包括发送的校验和).从最重要的位置进行忽略.

我发现的另一个描述是:校验和值包含数据消息中其他字的模256和的二进制补码(即消息类型,消息长度和数据字).接收设备可以计算接收字的模256和,并将该和加到接收的校验和字上.零结果通常表示消息已正确接收.

我理解这意味着我将消息中所有字节的值相加(excl校验和),得到这个数字的模256.获得这个数字的两个补码,这是我的校验和.

但是我遇到了一个示例消息示例的问题(来自设计文档,所以我必须假设它已经被正确编码).

unsigned char arr[] = {0x80,0x15,0x1,0x8,0x30,0x33,0x31,0x35,0x31,0x30,0x33,0x30,0x2,0x8,0x30,0x33,0x35,0x31,0x2d,0x33,0x32,0x31,0x30,0xe};
Run Code Online (Sandbox Code Playgroud)

所以最后一个字节0xE是校验和.我计算校验和的代码如下:

bool isMsgValid(unsigned char arr[], int len) {
   int sum = 0;
   for(int i = 0; i < (len-1); ++i) {
      sum += arr[i];
   }
   //modulo 256 sum
   sum %= 256;

   char ch = sum;

   //twos complement
   unsigned char twoscompl = ~ch + 1;

   return arr[len-1] == twoscompl;
}


int main(int argc, char* argv[])
{
   unsigned char arr[] = {0x80,0x15,0x1,0x8,0x30,0x33,0x31,0x35,0x31,0x30,0x33,0x30,0x2,0x8,0x30,0x33,0x35,0x31,0x2d,0x33,0x32,0x31,0x30,0xe};
   int arrsize = sizeof(arr) / sizeof(arr[0]);

   bool ret = isMsgValid(arr, arrsize);

   return 0;
}
Run Code Online (Sandbox Code Playgroud)

规范在这里:= http://www.sinet.bt.com/227v3p5.pdf

我假设我误解了所需的算法.知道如何创建这个校验和吗?

Flippin spec writer在他们的数据示例中犯了一个错误.刚发现它然后回到这里,发现其他人也发现了.对不起,如果我浪费你的时间.我将研究回复,因为它看起来像一些有用的注释,用于改进我的代码.

Emi*_*ier 5

您错误地复制了您链接的pdf中的示例消息.第二个参数长度是9个字节,但您在代码中使用了0x08.

当参数中确实有9个字节时,文档错误地在第三列中指出"8个字节".第二列正确地指出"00001001".

换句话说,您的测试消息应该是:

{0x80,0x15,0x1,0x8,0x30,0x33,0x31,0x35,0x31,0x30,0x33,0x30, // param1
 0x2,0x9,0x30,0x33,0x35,0x31,0x2d,0x33,0x32,0x31,0x30,0xe}  // param2
     ^^^
Run Code Online (Sandbox Code Playgroud)

使用正确的消息数组,ret == true当我尝试您的程序时.

  • 没问题.你应该听取其他人关于使用无符号类型的建议. (2认同)