首页 > 应用 > 物联网

用于打包和解包数据的C语言联合

Steve Arar 2019-08-08

前一篇文章讨论了最初的联合应用程序已经为互斥变量创建了一个共享内存区域。但随着时间的推移,程序员已广泛将联合用于完全不同的应用程序:从较大的数据对象中提取较小的数据部分。在本文中,我们将更详细地介绍这个联合的特定应用。eZK电子头条

 eZK电子头条

使用联合打包/解包数据eZK电子头条

 eZK电子头条

联合的成员存储在共享内存区域中。这是允许我们为联合找到有趣应用程序的关键功能。考虑下面的联合:eZK电子头条

 eZK电子头条

用于打包和解包数据的C语言联合eZK电子头条

 eZK电子头条

此联合中有两个成员:第一个成员“word”是一个双字节变量。第二个成员是两个单字节变量的结构。为联合分配的两个字节在其两个成员之间共享。分配的内存空间可以如下面的图1所示。eZK电子头条

 eZK电子头条

用于打包和解包数据的C语言联合eZK电子头条

图1 eZK电子头条

 eZK电子头条

“word”变量指的是整个分配的存储空间,“byte1”和“byte2”变量指的是构成“word”变量的单字节区域。如何使用此功能?假设有两个单字节变量“x”和“y”,它们应该组合起来产生一个双字节变量。在这种情况下,可以使用上面的联合并按如下方式将“x”和“y”分配给结构成员。eZK电子头条

 eZK电子头条

用于打包和解包数据的C语言联合eZK电子头条

 eZK电子头条

可以读取联合“word”成员来获得由“x”和“y”变量组成的双字节变量(参见图2)。eZK电子头条

 eZK电子头条

用于打包和解包数据的C语言联合eZK电子头条

图2eZK电子头条

 eZK电子头条

上面的例子显示了联合将两个单字节变量打包成一个双字节变量的使用。也可以反过来:将一个双字节值写入“word”并通过读取“x”和“y”变量将其解压缩为两个单字节变量。将值写入联合的一个成员并读取另一个成员,它有时被称为“数据压缩”。eZK电子头条


eZK电子头条

处理器端序eZK电子头条

 eZK电子头条

使用联合打包/解包数据时,需要注意处理器端序。正如Robert Keim关于端序的文章中所讨论的,该术语指定了数据对象的字节存储在内存中的顺序。处理器可以是小端或大端。对于大端处理器,数据的存储方式包含最高有效位的字节具有最低的存储器地址。在小端系统中,首先存储包含最低有效位的字节。图3中描述的示例说明了序列0x01020304的小端和大端存储。eZK电子头条

 eZK电子头条

用于打包和解包数据的C语言联合eZK电子头条

图3.图片由IAR提供。eZK电子头条

 eZK电子头条

使用以下代码来实验上一节的联合:eZK电子头条

 eZK电子头条

用于打包和解包数据的C语言联合eZK电子头条

 eZK电子头条

运行此代码,得到以下输出:Word是:0X4321。这表明共享存储空间的第一个字节(“u1.byte1”)用于存储“word”变量的最低有效字节(0X21)。换句话说,用来执行代码的处理器是小端。eZK电子头条

 eZK电子头条

如你所见,联合的特定应用程序可以表现出依赖于实现的行为。但是,这不应该是一个严重的问题,因为对于这种低级编码,通常知道处理器端序。如果不知道这些细节,可以使用上面的代码来了解数据在内存中的组织方式。eZK电子头条

 eZK电子头条

替代方案eZK电子头条

 eZK电子头条

可以使用按位运算符来执行数据打包或解包,而不是使用联合。例如,可使用以下代码组合两个单字节变量“byte3”和“byte4”,并生成一个双字节变量(“word2”):eZK电子头条

 eZK电子头条

用于打包和解包数据的C语言联合eZK电子头条

 eZK电子头条

比较这两个解决方案在小端和大端情况下的输出,参考以下代码:eZK电子头条

 eZK电子头条

用于打包和解包数据的C语言联合eZK电子头条

 eZK电子头条

如果为大端处理器(如TMS470MF03107)编译此代码,则输出将为:Word1:0X2143;Word2:0X2143。但是,如果为一个小端处理器(如STM32F407IE)编译它,输出将是:Word1:0X4321;Word2:0X2143。eZK电子头条

 eZK电子头条

基于联合的方法表现出依赖于硬件的行为,而不管处理器的字节顺序如何,基于移位操作的方法导致相同的结果。这是因为采用后一种方法,为变量名称(“word2”)赋值,编译器负责设备使用的内存组织。但是,使用基于联合的方法,正在更改构造“word1”变量的字节值。尽管基于联合的方法表现出依赖于硬件的行为,但它具有更易读和可维护的优点。这就是程序员喜欢在这个应用程序中使用联合的原因。eZK电子头条

 eZK电子头条

“数据压缩”的实例  eZK电子头条

 eZK电子头条

使用通用串行通信协议时,可能需要执行数据打包或解包。考虑在每个通信序列期间发送/接收一个字节数据的串行通信协议。只要使用一个字节长的变量,就可以很容易地传输数据,但是如果有一个应该通过通信链接的任意大小的结构呢?在这种情况下,必须以某种方式将数据对象表示为一个单字节长变量的数组。一旦得到这个字节表示数组,就可以通过通信链路传输字节。然后,在接收器端可以适当地打包它们并重建原始结构。eZK电子头条

 eZK电子头条

例如,假设需要通过UART通信发送一个浮点变量“f1”。浮点变量通常占用四个字节。因此可以使用以下联合作为缓冲区来提取“f1”的四个字节:eZK电子头条

 eZK电子头条

用于打包和解包数据的C语言联合eZK电子头条

 eZK电子头条

发送器将变量“f1”写入联合的浮动成员。然后,它读取“byte”数组并沿通信链路发送字节。接收器执行相反的操作:它将接收到的数据写入其自己的联合的“byte”数组,并读取联合的浮点变量作为接收值。可以使用这种技术来传输任意大小的数据对象。以下代码可以是验证此技术的简单测试。eZK电子头条

 eZK电子头条

用于打包和解包数据的C语言联合eZK电子头条

图4显示了所讨论的技术。请注意字节按顺序传输。 eZK电子头条

 eZK电子头条

用于打包和解包数据的C语言联合eZK电子头条

图4eZK电子头条

 eZK电子头条

总结eZK电子头条

 eZK电子头条

虽然最初的联合应用程序正在为互斥变量创建共享内存区域,但随着时间的推移,程序员已经广泛将联合用于完全不同的应用程序:使用联合进行数据打包/解包。联合的这种特殊应用涉及将值写入联合的一个成员并读取其中的另一个成员。eZK电子头条

 eZK电子头条

“数据压缩”或使用联合进行数据打包/解包可能导致依赖于硬件的行为。但是,它具有更易读和可维护的优点。这就是程序员喜欢在这个应用程序中使用联合的原因。当有一个应该通过串行通信链路的任意大小的数据对象时,“数据压缩”会特别有用。eZK电子头条