本文最后更新于 2024-02-22,文章好久没更新了。

字节对齐

前言

字节对齐在嵌入式开发中被广泛使用,但是大部分应用场景都是告诉大家在32位系统中使用4字节对齐来加快执行效率,而字节对齐远远不止这一点点功能,接下来为大家展示一个应用在协议解析的应用场景希望对大家有一定的帮助。

应用场景

比如一个报文结构要求如下所示实际使用中协议很难做到字节对齐。

0x59

整体标定

D0

UINT8

 

气体类型

 

斜率

D1~4

Float

 

 

 

截距

D5~8

Float

 

 

 

零点屏蔽值

D9~12

Float

 

 

 

。。。

 

 

 

 

使用传统方式将数据逐个字节去拼接

		case 0x59: // 整体标定
		{
			uint8_t len = pfrm->text[i + 1];

			for (size_t j = 0; j < (len - 1) / 13; j++)
			{data_0x83_59_t
				uint8_t gasType = pfrm->text[i + 2 + j * 13];
				uint8_t locType = ChnnelTocodeType(j);
				if (locType != 0xFF)
				{
					memcpy(&fVal_Slope, &pfrm->text[i + 3 + j * 13], sizeof(float));
					memcpy(&fVal_Intercept, &pfrm->text[i + 7 + j * 13], sizeof(float));
					memcpy(&fVal_zeromask, &pfrm->text[i + 11 + j * 13], sizeof(float));
					sysinfo->Sensor_SecCalib[locType].Slope = fVal_Slope;
					sysinfo->Sensor_SecCalib[locType].Intercept = fVal_Intercept;
					sysinfo->ZeroMaskValue[locType] = fVal_zeromask;
				}
			}
		}
		break;

使用结构体实现数据提取工作

#pragma pack(1) /*!< 1字节对齐 */
struct _DATA_0X83_59
{ // 整体标定
	uint8_t codetype;
	float slope;
	float intercept;
	float zeromask;
} data_0x83_59_t;
#pragma pack() /*!< 取消字节对齐 */

		case 0x59: // 整体标定
		{
			uint8_t len = pfrm->text[i + 1];

			for (size_t j = 0; j < (len - 1) / 13; j++)
			{
				data_0x83_59_t *ptr = pfrm->text[i + 2 + j * 13];
				uint8_t locType = ChnnelTocodeType(ptr->codetype);
				if (locType != 0xFF)
				{
					sysinfo->Sensor_SecCalib[locType].Slope = ptr->slope;
					sysinfo->Sensor_SecCalib[locType].Intercept = ptr->intercept;
					sysinfo->ZeroMaskValue[locType] = ptr->zeromask;
					;
				}
			}
		}

通过上下对比,可以明显发现下放代码的优越性,不仅提高了可读性,而且他的效率远高于人工处理,很多工作时可以交给编译器去解决提高我们的代码质量。

说明

#paragma pack(n) 编译器的字节对齐 n标识几字节对齐,32位环境默认是4字节对齐,

#paragma pack() 不写数值n则取消手动指定的对齐,恢复默认,我建议每个对齐后都要恢复默认,以免影响其它代码。