我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

算法介绍

循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。

CRC校验计算速度快,检错能力强,易于用编码器等硬件电路实现。从检错的正确率与速度、成本等方面,都比奇偶校验等校验方式具有优势。因而,CRC 成为计算机信息通信领域最为普遍的校验方式。常见应用有以太网/USB通信,压缩解压,视频编码,图像存储,磁盘读写等

参数模型

CRC参数模型

不知道你是否遇到过这种情况,同样的CRC多项式,调用不同的CRC计算函数,得到的结果却不一样,而且和手算的结果也不一样,这就涉及到CRC的参数模型了。计算一个正确的CRC值,需要知道CRC的参数模型。

一个完整的CRC参数模型应该包含以下信息:WIDTH,POLY,INIT,REFIN,REFOUT,XOROUT。

NAME:参数模型名称。

WIDTH:宽度,即生成的CRC数据位宽,如CRC-8,生成的CRC为8位

POLY:十六进制多项式,省略最高位1,如 x8 + x2 + x + 1,二进制为1 0000 0111,省略最高位1,转换为十六进制为0x07。

INIT:CRC初始值,和WIDTH位宽一致。

REFIN:true或false,在进行计算之前,原始数据是否翻转,如原始数据:0x34 = 0011 0100,如果REFIN为true,进行翻转之后为0010 1100 = 0x2c

REFOUT:true或false,运算完成之后,得到的CRC值是否进行翻转,如计算得到的CRC值:0x97 = 1001 0111,如果REFOUT为true,进行翻转之后为11101001 = 0xE9。

XOROUT:计算结果与此参数进行异或运算后得到最终的CRC值,和WIDTH位宽一致。

接收端的校验有两种方式:

  • 一种是和CRC计算一样,在本地把接收到的数据和CRC分离,然后在本地对数据进行CRC运算,得到的CRC值和接收到的CRC进行比较,如果一致,说明数据接收正确,如果不一致,说明数据有错误。
  • 另一种方法是把整个数据帧进行CRC运算,因为是数据帧相当于把原始数据左移8位,然后加上余数,如果直接对整个数据帧进行CRC运算(除以多项式),那么余数应该为0,如果不为0说明数据出错

代码计算

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//求数的二进制最高位的幂指数,即MSB
static int getMinPolynomialBits(uint64_t n) {
	int r = 0;
	while (n >>= 1) r++;
	return r;
}

//append>0表示计算crc校验码,赋值到crcRemainder
//append=0,表示校验输入bit流是否正确;0表示正确,-1表示错误
//此处的多项式默认为0x96(高位补1后的结果),默认crc位数为7,可根据代码自行修改
static int crcCheck(const char* msg, int append, char* crcRemainder)
{
	if (msg == NULL || crcRemainder == NULL || strlen(msg) == 0) {
		printf("input parameter is unvalid!\n");
		return -1;
	}
	 //hex: 0x96 = b'10010110' = DEC:150 
	uint64_t poly = 0x96; 
	int polyLen = getMinPolynomialBits(poly + 1); //=7

	int msgLen = strlen(msg);
	//printf("%d\n", msgLen);

	//计算crc校验码
	if (append) {
		unsigned char* pBufCrc = (unsigned char*)calloc(msgLen + polyLen, sizeof(unsigned char)); 
		memset(pBufCrc, 0, msgLen + polyLen);

		for (int j = 0; j < msgLen; j++) {
			pBufCrc[j] = msg[j] - '0';
		}

		uint8_t* p = NULL;
		for (int i = 0; i < msgLen; i++) {
			if (pBufCrc[i]) {
				p = pBufCrc + i + polyLen;
				uint64_t t = poly;
				do {
					*(p--) ^= t & 1;
				} while (t >>= 1);
			}
		}
		p = NULL;

		size_t k;
		for (k = 0; k < polyLen; k++) {
			crcRemainder[k] = pBufCrc[k + msgLen] + 48;
		}
		if (pBufCrc) {
			free(pBufCrc);
			pBufCrc = NULL;
		}
	}
	else {
		// 校验接受端的比特流
		unsigned char* pBuffer = (unsigned char*)calloc(msgLen, sizeof(unsigned char)); 
		memset(pBuffer, 0, msgLen);

		int inforLen = msgLen - polyLen;//提取出信息流部分,然后计算当前信息对应crc校验码

		for (int j = 0; j < inforLen; j++) {
			pBuffer[j] = msg[j] - '0';
		}

		uint8_t* p = NULL;
		for (int i = 0; i < inforLen; i++) {
			if (pBuffer[i]) {
				p = pBuffer + i + polyLen;
				uint64_t t = poly;
				do {
					*(p--) ^= t & 1;
				} while (t >>= 1);
			}
		}
		p = NULL;

		//计算得到的crc码和输入的crc码进行对比验证,若每一位都相同,则校验成功
		for (size_t k = inforLen; k < msgLen; k++) {
			if (msg[k] != pBuffer[k] + 48) {
				if (pBuffer) {
					free(pBuffer);
					pBuffer = NULL;
				}
				return -1;
			}
		}
		if (pBuffer) {
			free(pBuffer);
			pBuffer = NULL;
		}
	}
	return 0;
}

到此这篇关于C/C++实现crc码计算和校验的文章就介绍到这了,更多相关C++ crc码内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

循环冗余校验(CyclicRedundancyCheck,CRC)是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术。本文主要介绍了C++实现crc码计算和校验的方法,需要的可以参考一下
2023-03-10

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

这篇文章主要讲解了“C/C++如何实现crc码计算和校验”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C/C++如何实现crc码计算和校验”吧!算法介绍循环冗余校验(Cyclic Redun
2023-07-05

怎么计算CRC循环冗余校验码

CRC(Cyclic Redundancy Check)循环冗余校验码是一种常用的数据校验方法,用于检测数据传输或存储过程中的错误。计算CRC循环冗余校验码的步骤如下:1.选择一个生成多项式,通常为一个二进制数。生成多项式的选择取决于所
2023-10-23

CRC校验原理及其C语言实现详解

循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术。本文主要介绍了CRC校验原理及其C语言实现,感兴趣的可以了解一下
2023-03-10

CRC校验原理及C语言实现的方法是什么

这篇“CRC校验原理及C语言实现的方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“CRC校验原理及C语言实现的方法是
2023-07-05

C++开发经验分享:C++云计算编程的实践经验

C++开发经验分享:C++云计算编程的实践经验云计算是当前IT行业的一个热点领域,也是未来发展方向之一。而作为一门经典且强大的编程语言,C++在云计算领域也扮演着重要的角色。在云计算的实践过程中,我们可以通过C++来实现高效、可靠、可伸缩的
C++开发经验分享:C++云计算编程的实践经验
2023-11-22

C++ Protobuf实现接口参数自动校验详解

用C++做业务发开的同学是否还在不厌其烦的编写大量if-else模块来做接口参数校验呢?今天,我们就模拟Java里面通过注解实现参数校验的方式来针对C++ protobuf接口实现一个更加方便、快捷的参数校验自动工具,希望对大家有所帮助
2023-05-16

C# md5 算法实现代码

相对C#来说,md5算法就相对简单很多,因为 System.Security.Cryptography; 已经包含了md5算法。所以我们只需创建MD5类对象即可实现md5算法,今天通过本文给大家介绍C# md5 算法实现,感兴趣的朋友一起看看吧
2022-11-13

C#实现远程关闭和重启计算机的示例代码

这篇文章主要为大家详细介绍了如何利用C#实现远程关闭和重启计算机的功能,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
2022-12-29

C语言实现计算器的代码怎么写

这篇文章主要介绍了C语言实现计算器的代码怎么写的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言实现计算器的代码怎么写文章都会有所收获,下面我们一起来看看吧。C语言计算器两种方法//一般做法#include<
2023-06-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录