C++|CRC校验总结

参考:
Vector - CAPL - CRC算法介绍
开发工具 > CRC校验工具

文章目录

  • 简介
  • CRC-8
  • CRC-16
  • CRC-32

简介

循环冗余校验(Cyclic Redundancy Check,简称CRC)是一种数据校验算法,广泛用于检测数据传输或存储过程中的错误。它通过计算数据的校验和来检测数据是否在传输过程中发生了错误。以下是几种常用的CRC校验算法:
CRC-8

  • 多项式:常用的多项式有 0x07(x^8 + x^2 + x + 1)、0x31(x^8 + x^5 + x^4 + 1)等。
  • 应用:常用于简单的数据校验,如一些简单的通信协议中。

CRC-16

  • 多项式:常用的多项式有 0x8005(x^16 + x^15 + x^2 + 1)、0xA001(x^16 + x^13 + x^12 + x^11 + x^10 + x^8 + x^5 + x^2 + 1)等。
  • 应用:广泛用于各种通信协议和文件格式中,如Modbus协议、MPEG-2等。

CRC-32

  • 多项式:最常用的是 0x04C11DB7(x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1)。
  • 应用:广泛应用于网络协议(如以太网)、文件压缩(如ZIP文件)、文件系统(如FAT32)等。

CRC-64

  • 多项式:常用的多项式有 0x42F0E1EBA9EA3693(ECMA-182标准)等。
  • 应用:用于需要更高校验精度的场合,如大型文件的完整性校验。

CRC算法特点

  • 简单高效:CRC算法相对简单,计算速度快,适合实时数据传输校验。
  • 检测能力:能有效检测突发错误(burst errors),即连续的错误比特。
  • 可配置性:通过选择不同的多项式,可以适应不同的应用场景和错误检测需求。

CRC算法实现
CRC算法通常通过位操作实现,包括位移、异或等操作。对于不同的多项式和数据长度,可以预先计算出一个查找表(lookup table),以提高计算效率。例如,CRC-32算法在许多编程语言中都有现成的库函数可供使用。
CRC算法虽然能有效检测数据错误,但不能纠正错误,因此在需要纠错的场合,还需要结合其他纠错编码技术。

在CRC校验中常见的主要有CalculateCRC8、CalculateCRC8H2F、CalculateCRC16、CalculateCRC32、CalculateCRC32P4、CalculateCRC64。

CRC-8

宽度:8位 多项式:0x07 初始值:0x00 异或值:00


#include <iostream>
#include <vector>
#include <cstdint>

template <typename Container>
static uint8_t calculateCRC8(const Container& data, int  len)
{
    uint8_t   InitCrc = 0x07;
    uint8_t crc = 0;
    int  i, j;

    for (i = 0; i < len; i++) {
        crc ^= data[i];
        for (j = 0; j < 8; j++) {
            if (crc & 0x80) {
                crc = (crc << 1) ^ InitCrc;
            }
            else {
                crc <<= 1;
            }
        }
    }
    return crc;
}

int main()
{
    // 创建一个样本数据
    std::vector<uint8_t> data = { 0x01, 0x02, 0x03, 0x04, 0x05 };
    // 计算整个数据的 CRC8
    uint8_t crc = calculateCRC8(data,data.size());
    // 输出结果
    std::cout << "CRC8: 0x" << std::hex << static_cast<int>(crc) << std::endl;
    // 检查结果是否符合预期
    // 假设我们预期的 CRC8 值是 0x9B
    uint8_t expected_crc = 0xBC;
    if (crc == expected_crc) {
        std::cout << "CRC8 calculation is correct." << std::endl;
    }
    else {
        std::cout << "CRC8 calculation is incorrect." << std::endl;
    }
}

在这里插入图片描述

CRC-16

宽度:16位 多项式:0x07 初始值:0x00 异或值:00

#include <iostream>
#include <vector>
#include <cstdint>

// 反转一个8位的值
uint8_t reverseBits(uint8_t value) {
    uint8_t result = 0;
    for (int i = 0; i < 8; i++) {
        result = (result << 1) | (value & 1);
        value >>= 1;
    }
    return result;
}

template <typename Container>
static uint16_t calculateCRC16(const Container& data, int len) {
    // CRC-16多项式,x^16 + x^15 + x^2 + 1
    uint16_t polynomial = 0x8005;
    // CRC-16初始值
    uint16_t crc = 0x0000;
    int i, j;

    for (i = 0; i < len; i++) {
        // 反转数据字节
        uint8_t reversedData = reverseBits(data[i]);
        crc ^= static_cast<uint16_t>(reversedData) << 8;
        for (j = 0; j < 8; j++) {
            if (crc & 0x8000) {
                crc = (crc << 1) ^ polynomial;
            }
            else {
                crc <<= 1;
            }
        }
    }
    // 反转最终的CRC值
    crc = (crc >> 8) | (crc << 8);
    crc = reverseBits(static_cast<uint8_t>(crc & 0xFF)) | (reverseBits(static_cast<uint8_t>(crc >> 8)) << 8);
    return crc;
}

int main() {
    // 创建一个样本数据
    std::vector<uint8_t> data = { 0x01, 0x02, 0x03, 0x04, 0x05 };

    // 计算整个数据的CRC-16
    uint16_t crc = calculateCRC16(data, data.size());

    // 输出结果
    std::cout << "CRC-16: 0x" << std::hex << crc << std::endl;

    // 检查结果是否符合预期
    // 假设我们预期的CRC-16值是0xXXXX
    uint16_t expected_crc = 0xbb0e; // 请根据实际情况替换为预期值
    if (crc == expected_crc) {
        std::cout << "CRC-16 calculation is correct." << std::endl;
    }
    else {
        std::cout << "CRC-16 calculation is incorrect." << std::endl;
    }
}

在这里插入图片描述

CRC-32

改了半天终于对了,可能和大小端有关系
从您的描述和计算结果来看,问题可能出在几个方面:

  1. 反向字节的顺序:在计算 CRC32 时,通常字节顺序和位顺序是反转的。即字节顺序按反向处理,而每个字节内的位也需要反转。
  2. 正确的 CRC32 算法实现:我们应该确保按标准的 CRC32 算法来进行处理。最常见的 CRC32 是基于 ISO 802.3
    标准,它的计算方法会要求从一个初始化值开始,对每个字节进行计算并使用最终的异或值。
  3. 字节处理顺序和位反转:需要确保数据和多项式都正确地按照字节顺序(小端序或大端序)来处理。
#include <iostream>
#include <vector>
#include <cstdint>
#include <iomanip> // 用于格式化输出

const uint32_t CRC32_POLY = 0xEDB88320; // 反向多项式
const uint32_t CRC32_INIT = 0xFFFFFFFF; // CRC-32初始值
const uint32_t CRC32_XOR_OUT = 0xFFFFFFFF; // CRC-32最终异或值

// CRC32查找表
uint32_t crc32Table[256];

// 初始化CRC32查找表
void initCRC32Table() {
    for (uint32_t i = 0; i < 256; ++i) {
        uint32_t crc = i;
        for (uint32_t j = 8; j > 0; --j) {
            if (crc & 1) {
                crc = (crc >> 1) ^ CRC32_POLY;
            }
            else {
                crc >>= 1;
            }
        }
        crc32Table[i] = crc;
    }
}

// 计算CRC32
uint32_t calculateCRC32(const std::vector<uint8_t>& data) {
    uint32_t crc = CRC32_INIT;

    for (size_t i = 0; i < data.size(); ++i) {
        uint8_t byte = data[i];
        crc = (crc >> 8) ^ crc32Table[(crc ^ byte) & 0xFF];
    }

    crc ^= CRC32_XOR_OUT;
    return crc;
}

int main() {
    // 初始化CRC32查找表
    initCRC32Table();

    // 待校验的数据
    std::vector<uint8_t> data = { 0x01, 0x02, 0x03, 0x04, 0x05 , 0x06 };

    // 计算CRC-32校验值
    uint32_t crc = calculateCRC32(data);

    // 输出CRC-32校验值
    std::cout << "CRC-32: 0x" << std::hex << std::uppercase << std::setw(8) << std::setfill('0') << crc << std::endl;

    // 检查结果是否符合预期
    uint32_t expected_crc = 0x81F67724; // 预期的CRC-32值
    if (crc == expected_crc) {
        std::cout << "CRC-32 calculation is correct." << std::endl;
    }
    else {
        std::cout << "CRC-32 calculation is incorrect." << std::endl;
    }

    return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/954192.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】11.Linux基础开发工具使用(4)

文章目录 3. Linux调试器-gdb使用3.1 背景3.2 下载安装3.3 使用gdb查询3.4 开始使用 3. Linux调试器-gdb使用 3.1 背景 程序的发布方式有两种&#xff0c;debug模式和release模式 Linux gcc/g出来的二进制程序&#xff0c;默认是release模式 要使用gdb调试&#xff0c;必须…

windows系统“acadres.dll”文件丢失或错误导致游戏运行异常如何解决?windows系统DLL文件修复方法

acadres.dll是存放在windows系统中的一个重要dll文件&#xff0c;缺少它可能会造成部分游戏不能正常运行。当你的电脑弹出提示“无法找到acadres.dll”或“计算机缺少acadres.dll”等错误问题&#xff0c;请不用担心&#xff0c;我们将深入解析DLL文件错误的成因&#xff0c;并…

小程序如何引入腾讯位置服务

小程序如何引入腾讯位置服务 1.添加服务 登录 微信公众平台 注意&#xff1a;小程序要企业版的 第三方服务 -> 服务 -> 开发者资源 -> 开通腾讯位置服务 在设置 -> 第三方设置 中可以看到开通的服务&#xff0c;如果没有就在插件管理中添加插件 2.腾讯位置服务…

【AIGC-ChatGPT进阶提示词指令】心灵修复师:一个基于情感共鸣的智慧对话系统设计

引言 在当今快节奏的生活中&#xff0c;心理健康问题日益凸显。如何借助人工智能技术&#xff0c;构建一个既富有温度又专业可靠的心理支持系统&#xff0c;成为了一个值得深入探讨的课题。本文将详细介绍一个名为"心灵修复师"的对话系统设计&#xff0c;这个系统通…

计算机网络 (44)电子邮件

一、概述 电子邮件&#xff08;Electronic Mail&#xff0c;简称E-mail&#xff09;是因特网上最早流行的应用之一&#xff0c;并且至今仍然是因特网上最重要、最实用的应用之一。它利用计算机技术和互联网&#xff0c;实现了信息的快速、便捷传递。与传统的邮政系统相比&#…

《leetcode-runner》【图解】如何手搓一个debug调试器——调试程序【JDI开发】【万字详解】

前文&#xff1a; 《leetcode-runner》如何手搓一个debug调试器——引言 《leetcode-runner》如何手搓一个debug调试器——架构 《leetcode-runner》如何手搓一个debug调试器——指令系统 本文主要聚焦于如何编写调试程序 背景 在leetcode算法背景下&#xff0c;用户只编写了…

小米vela系统(基于开源nuttx内核)——openvela开源项目

前言 在 2024 年 12 月 27 日的小米「人车家全生态」合作伙伴大会上&#xff0c;小米宣布全面开源 Vela 操作系统。同时&#xff0c;OpenVela 项目正式上线 GitHub 和 Gitee&#xff0c;采用的是比较宽松的 Apache 2.0 协议&#xff0c;这意味着全球的开发者都可以参与到 Vela…

【 PID 算法 】PID 算法基础

一、简介 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&#xff09;、Differential&#xff08;微分&#xff09;的缩写。也就是说&#xff0c;PID算法是结合这三种环节在一起的。粘一下百度百科中的东西吧。 顾名思义&#xff0c;…

使用 WPF 和 C# 绘制覆盖网格的 3D 表面

此示例展示了如何使用 C# 代码和 XAML 绘制覆盖有网格的 3D 表面。示例使用 WPF 和 C# 将纹理应用于三角形展示了如何将纹理应用于三角形。此示例只是使用该技术将包含大网格的位图应用于表面。 在类级别&#xff0c;程序使用以下代码来定义将点的 X 和 Z 坐标映射到 0.0 - 1.…

为深度学习创建PyTorch张量 - 最佳选项

为深度学习创建PyTorch张量 - 最佳选项 正如我们所看到的&#xff0c;PyTorch张量是torch.Tensor​ PyTorch类的实例。张量的抽象概念与PyTorch张量之间的区别在于&#xff0c;PyTorch张量为我们提供了一个可以在代码中操作的具体实现。 在上一篇文章中&#xff0c;我们看到了…

Linux下源码编译安装Nginx1.24及服务脚本实战

1、下载Nginx [rootlocalhost ~]# wget -c https://nginx.org/download/nginx-1.24.0.tar.gz2、解压 [rootlocalhost ~]# tar xf nginx-1.24.0.tar.gz -C /usr/local/src/3、安装依赖 [rootlocalhost ~]# yum install gcc gcc-c make pcre-devel openssl-devel -y4、 准备 N…

4、dockerfile实现lnmp和elk

dockerfile实现lnmp 使用dockerfile n&#xff1a;nginx&#xff0c;172.111.0.10 m&#xff1a;mysql&#xff0c;172.111.0.20 p&#xff1a;php&#xff0c;172.111.0.30 安装配置nginx 1、准备好nginx和wordpress安装包 2、配置dockerfile 3、配置nginx主配置文件ngin…

一文通透OpenVLA及其源码剖析——基于Prismatic VLM(SigLIP、DinoV2、Llama 2)及离散化动作预测

前言 当对机器人动作策略的预测越来越成熟稳定之后(比如ACT、比如扩散策略diffusion policy)&#xff0c;为了让机器人可以拥有更好的泛化能力&#xff0c;比较典型的途径之一便是基于预训练过的大语言模型中的广泛知识&#xff0c;然后加一个policy head(当然&#xff0c;一开…

《操作系统真象还原》第十三章——磁盘驱动程序

文件系统磁盘创建 创建磁盘 进入bochs安装目录&#xff0c;输入以下命令 ./bin/bximage 然后按照以下步骤创建硬盘 修改硬盘配置 vim boot.disk 添加以下代码行 ata0-slave: typedisk, path"hd80M.img", modeflat,cylinders162,heads16,spt63 完整配置如下 …

快速、可靠且高性价比的定制IP模式提升芯片设计公司竞争力

作者&#xff1a;Karthik Gopal&#xff0c;SmartDV Technologies亚洲区总经理 智权半导体科技&#xff08;厦门&#xff09;有限公司总经理 无论是在出货量巨大的消费电子市场&#xff0c;还是针对特定应用的细分芯片市场&#xff0c;差异化芯片设计带来的定制化需求也在芯片…

v-bind操作class

v-bind操作class 参考文献&#xff1a; Vue的快速上手 Vue指令上 Vue指令下 Vue指令的综合案例 指令的修饰符 文章目录 v-bind操作classv-bind对于样式控制的增强操作class案例(tab导航高亮)操作style操作style案例 结语 博客主页: He guolin-CSDN博客 关注我一起学习&#…

Kubernetes1.28 编译 kubeadm修改证书有效期到 100年.并更新k8s集群证书

文章目录 前言一、资源准备1. 下载对应源码2.安装编译工具3.安装并设置golang 二、修改证书有效期1.修改证书有效期2.修改 CA 证书有效期 三、编译kubeadm四、使用新kubeadm方式1.当部署新集群时,使用该kubeadm进行初始化2.替换现有集群kubeadm操作 前言 kubeadm 默认证书为一…

HarmonyOS NEXT应用开发边学边玩系列:从零实现一影视APP (三、影视搜索页功能实现)

在HarmonyOS NEXT开发环境中&#xff0c;我们可以使用nutpi/axios库来简化网络请求的操作。本文将展示如何使用HarmonyOS NEXT框架和nutpi/axios库&#xff0c;从零开始实现一个简单的影视APP&#xff0c;主要关注影视搜索页的功能实现。 为什么选择nutpi/axios&#xff1f; n…

高级运维:shell练习2

1、需求&#xff1a;判断192.168.1.0/24网络中&#xff0c;当前在线的ip有哪些&#xff0c;并编写脚本打印出来。 vim check.sh #!/bin/bash# 定义网络前缀 network_prefix"192.168.1"# 循环遍历1-254的IP for i in {1..254}; do# 构造完整的IP地址ip"$network_…

好用的php商城源码有哪些?

选择一个优秀的商城工具&#xff0c;能更好地帮助大家建立一个好用的商城系统。目前比较流行的都是开源PHP商城系统&#xff0c;那么现实中都有哪些好用的PHP商城源码值得推荐呢&#xff1f;下面就带大家一起来了解一下。 1.TigShop 【推荐指数】&#xff1a;★★★★★☆ 【推…