C/C++实现crc码计算和校验

C/C++实现CRC码计算和校验

简介

CRC(Cyclic Redundancy Check)循环冗余校验码是一种通过计算来检测数据传输错误的方法,它通过对数据进行简单的计算得到一个固定长度的校验码,根据接收方收到的数据计算出的校验码和发送方计算出来的校验码进行比较来判断数据传输是否正确。

本文将介绍如何实现C/C++版的CRC码计算和校验,同时提供两个示例来说明如何使用。

CRC算法

对于一个要传输的数据d,CRC算法会计算出一个固定大小的校验码C,加上数据d和校验码C之后拼接成新的数据D,发送。接收方收到数据D之后,会计算接收到的数据的校验码C',如果C'与发送方计算出的校验码C一致,就说明数据传输正确无误。

通常我们使用的CRC算法都是基于多项式的下面这个公式计算得到的:

CRC(x) = r(x) mod g(x)

其中,x表示位,r(x)是要计算的数据,g(x)是一个系数多项式,mod是一个取模运算。

对于一个数据r(x)和一个G(x)多项式,执行CRC计算的过程如下:

  1. 将r(x)的高位填充G(x)的系数位数个0,得到p(x)
  2. 对p(x)和G(x)进行异或操作,得到余数d(x),把d(x)存储到p(x)的最高位
  3. 把p(x)的高位弹出,转到第二步,直到所有r(x)的位数处理完毕

最终得到的p(x)就是计算出的CRC码。接收方收到数据之后也用同样的算法计算出接收到的数据的CRC码,如果接收方计算出的CRC码与发送方计算出的CRC码相同,则说明数据传输正确。

C/C++实现

在C/C++中,我们可以通过计算得到一个数据的CRC码,也可以在接收到数据后计算数据的CRC码并校验。

CRC码计算

在C/C++中,计算CRC码的过程可以用一个函数来实现。我们可以定义一个函数,它接收一个指向数据的指针和数据的长度,同时再定义一个G(x)系数多项式,函数会返回计算出的CRC码。

一个常用的CRC16算法如下:

uint16_t CRC16(uint8_t *pdata, uint32_t len, uint16_t polynominal) {
    uint16_t crc = 0xFFFF;
    uint8_t i;
    while (len--) {
        crc ^= *pdata++;
        for (i = 0; i < 8; i++) {
            if (crc & 0x0001) {
                crc >>= 1;
                crc ^= polynominal;
            }
            else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

该函数接收三个参数,pdata表示数据的指针,len表示数据长度,polynominal表示多项式系数。函数首先初始化一个crc变量为0xFFFF,然后对于每一个数据位执行一次循环,对于每一位,执行一次异或运算,然后进行8次迭代,每一次迭代都判断是否需要执行异或操作,最终得到的crc值就是计算出的CRC码。

CRC码校验

在C/C++中,校验CRC码的过程也可以用一个函数来实现。与计算CRC码的过程类似,校验CRC码的函数需要接收一个指向数据的指针和数据的长度以及一个该数据对应的CRC码。

一个常用的CRC16校验函数如下:

bool CheckCRC16(uint8_t *pdata, uint32_t len, uint16_t crc, uint16_t polynominal) {
    uint16_t crc_calculated = CRC16(pdata, len, polynominal);
    return crc == crc_calculated;
}

该函数接收四个参数,pdata表示数据的指针,len表示数据长度,crc表示接收到的CRC码,polynominal表示多项式系数。函数首先调用计算CRC码的函数计算出接收到的数据的CRC码,然后判断计算出的CRC码是否与接收到的CRC码相等,如果相等则返回true,否则返回false。

示例

下面我们提供两个示例来说明怎样使用C/C++来实现CRC码计算和校验。

示例一:计算字符串CRC码

#include <stdio.h>
#include <stdint.h>

/*CRC16多项式*/
const uint16_t POLYNOMIAL = 0xA001;

/*计算CRC16*/
uint16_t CRC16(uint8_t *pdata, uint32_t len, uint16_t polynominal) {
    uint16_t crc = 0xFFFF;
    uint8_t i;
    while (len--) {
        crc ^= *pdata++;
        for (i = 0; i < 8; i++) {
            if (crc & 0x0001) {
                crc >>= 1;
                crc ^= polynominal;
            }
            else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

int main() {
    uint8_t data[] = {"Hello World!"};
    uint32_t len = sizeof(data);
    uint16_t crc_calculated = CRC16(data, len - 1, POLYNOMIAL);
    printf("CRC16: %04X\n", crc_calculated);
    return 0;
}

该示例演示了如何计算字符串的CRC16码。在主函数中,我们定义了一个字符串变量data,该字符串包含13个字符,分别为“Hello World!”,我们将该字符串作为数据,调用CRC16函数计算它的CRC16码,最终输出计算出的CRC16码。

示例二:校验接收到的数据

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

/*CRC16多项式*/
const uint16_t POLYNOMIAL = 0xA001;

bool CheckCRC16(uint8_t *pdata, uint32_t len, uint16_t crc, uint16_t polynominal) {
    uint16_t crc_calculated = CRC16(pdata, len, polynominal);
    return crc == crc_calculated;
}

int main() {
    uint8_t data[] = {"Hello World!"};
    uint32_t len = sizeof(data);
    /*模拟接收到的数据(包含CRC码)*/
    uint8_t received_data[] = { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x94, 0x62 };
    /*从数据中提取CRC码*/
    uint16_t crc = received_data[len - 2] << 8 | received_data[len - 1];

    /*校验CRC码*/
    bool result = CheckCRC16(data, len - 1, crc, POLYNOMIAL);
    if (result) {
        printf("CRC Check passed.\n");
    }
    else {
        printf("CRC Check failed.\n");
    }
    return 0;
}

该示例演示了如何校验接收到的数据的CRC码。在主函数中,我们定义了一个字符串变量data,该字符串包含13个字符,分别为“Hello World!”,我们将该字符串作为数据,然后模拟接收到了一组数据,其中包含了我们发送的数据以及计算出的CRC码。我们从接收到的数据中提取出CRC码,然后调用CheckCRC16函数校验接收到的数据的CRC码是否正确,最终输出校验结果。

结论

本文介绍了如何在C/C++中实现CRC码计算和校验,通过两个示例演示了如何计算字符串的CRC码以及如何校验接收到的数据的CRC码。希望能帮助到需要进行CRC码计算和校验的读者。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C/C++实现crc码计算和校验 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • Python机器学习之AdaBoost算法

    Python机器学习之AdaBoost算法 简介 AdaBoost(Adaptive Boosting)是一个非常流行的机器学习算法,它能够提高弱分类算法的准确性。其中,“自适应”指的是每个分类器的权重会随着准确率的变化而动态调整,而“增量”则表示每个分类器都是基于之前分类器的结果进行训练的。 原理 AdaBoost的基本算法如下: 初始化数据集权重 $w_…

    C 2023年5月23日
    00
  • C++设计模式之单例模式详解

    下面是详细讲解“C++设计模式之单例模式详解”的完整攻略。 什么是单例模式? 单例模式是一种创建型设计模式,用于确保类只有一个实例,并提供全局访问点。 为什么使用单例模式? 在某些情况下,我们需要确保在整个应用程序中只有一个实例化对象。单例模式使我们能够确保这一点。此外,单例模式还可以提供全局访问点,以便在应用程序中的任何地方都可以轻松访问单例对象。 实现单…

    C 2023年5月22日
    00
  • go GCM gin中间件的加密解密文件流处理

    GCM是一种加密方式,它能够提供认证和加密的安全性,并且应用范围广泛。在Go语言中,我们可以通过gin框架中的中间件来实现GCM加密解密文件流处理。 下面我们就来一步步讲解如何实现。 引入必要的包 在Go语言中,实现GCM加密解密流处理,我们需要使用到以下包: import ( "crypto/aes" "crypto/ciph…

    C 2023年5月23日
    00
  • C++实现航空订票程序

    C++实现航空订票程序 程序设计 题目描述:设计一个航空订票系统,要求能够查询航班、预订航班、退订航班等功能。 程序设计思路:将航班信息、旅客信息以及订单信息进行数据结构的设计,然后通过调用相应的函数实现不同的功能。 程序代码 数据结构: //航班信息结构体 struct flight{ string flightno; //航班号 string depar…

    C 2023年5月23日
    00
  • C语言:利用指针编写程序,用梯形法计算给定的定积分实例

    利用指针编写程序,用梯形法计算给定的定积分 一、梯形法简介 梯形法是一种基本的数值积分方法,它的思想是将要求解的定积分区间等分成若干小区间,每个小区间内的函数曲线视为一条直线段,进而将小区间视为一个梯形,因此得名梯形法。 二、程序设计思路 用户输入被积函数的表达式及积分区间端点,步长,以及误差限制等参数; 计算区间内小梯形的面积; 根据误差限制和小梯形的总面…

    C 2023年5月23日
    00
  • C语言/C++如何生成随机数

    生成随机数在编程中是一个常见的需求,C语言和C++都提供了相应的库函数来生成随机数。下面是生成随机数的完整攻略: 包含头文件 在C语言中需要包含stdlib.h头文件,而在C++中需要包含头文件,才可以使用生成随机数的函数。 // C语言 #include <stdlib.h> // C++语言 #include <random> s…

    C 2023年5月22日
    00
  • C 程序 二进制转换为八进制

    下面是关于“C 程序 二进制转换为八进制”的完整使用攻略。 标题 C 程序二进制转换为八进制的完整使用攻略 介绍 在计算机领域中,二进制和八进制是两种常用的进制。我们可以使用 C 程序将二进制数字转换为八进制数字。在本文中,我们将讨论如何实现这项任务。 步骤 以下是将二进制转换为八进制的步骤: 我们需要在程序中接受一个二进制数字输入。 将输入的二进制数进行逐…

    C 2023年5月9日
    00
  • 流放之路3.0决斗者处刑者双手武器旋风斩BD介绍

    流放之路3.0决斗者处刑者双手武器旋风斩BD介绍 前言 双手武器旋风斩决斗者是一个非常常见的选择,它对于大多数情况都有很好的适应性。下面我来为大家详细介绍这个BD的技能、装备和天赋选择。 技能选择 主要技能 旋风斩:BD的主要输出技能,必须保持在5层狂怒状态下释放,可以让周围的敌人都受到伤害,而且施法时间很短。 督军的战斧:可以提供伤害加成,增加自身暴击率,…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部