该 pragma 定义了数据结构在分配过程中的打包方式。属性必须插入数据结构的上方,并影响整个结构的打包。
语法 :
{attribute 'pack_mode' := ' <pack mode value>' }
插入位置:数据结构声明上方
|
<包装模式值> |
相关包装方法 |
说明 |
|---|---|---|
|
0 |
对齐 |
所有变量都以字节地址分配。没有记忆空白。 |
|
1 |
1 字节对齐 |
|
|
2 |
2 字节对齐 |
有
|
|
4 |
4 字节对齐 |
有
|
|
8 |
8 字节对齐 |
有
|
根据结构的不同,各个模式的内存映射可能没有区别。因此,<pack mode value> = 4 结构的内存分配可以与<pack mode value> = 8 结构的内存分配相对应。
结构阵列如果结构以数组形式组合,则在结构末尾添加字节,以便下一个结构对齐。




注意

如果在符号配置中选择了“Compatibility layout” 选项,同时又在代码中使用了属性 "pack_mode",那么可能会由于无意的内存错位而出现问题。
另见
示例 1
示例
{attribute 'pack_mode' := '1'}
TYPE myStruct:
STRUCT
Enable: BOOL;
Counter: INT;
MaxSize: BOOL;
MaxSizeReached: BOOL;
END_STRUCT
END_TYPE
数据类型为myStruct 的变量的内存范围是 "对齐 "分配的。例如,如果其组件Enable 的存储地址为0x0100 ,则组件Counter 的地址为0x0101 ,MaxSize 的地址为0x0103 ,MaxSizeReached 的地址为0x0104 。就'pack_mode':=2 而言,Counter 位于0x0102 ,MaxSize 位于0x0104 ,MaxSizeReached 位于0x0106 。
示例 2
示例
STRUCT Var1 : BOOL := 16#01; Var2 : BYTE := 16#11; Var3 : WORD := 16#22; Var4 : BYTE := 16#44; Var5 : DWORD := 16#88776655; Var6 : BYTE := 16#99; Var7 : BYTE := 16#AA; Var8 : DWORD := 16#AA; END_TYPE
|
pack_mode = 0 |
pack_mode = 1 |
pack_mode = 2 |
pack_mode = 4 |
pack_mode = 8 |
||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
可变 |
数值 |
可变 |
数值 |
可变 |
数值 |
可变 |
数值 |
可变 |
数值 |
|
|
0 |
Var1 |
01 |
Var1 |
01 |
Var1 |
01 |
Var1 |
01 |
Var1 |
01 |
|
1 |
Var2 |
11 |
Var2 |
11 |
Var2 |
11 |
Var2 |
11 |
Var2 |
11 |
|
2 |
Var3 |
22 |
Var3 |
22 |
Var3 |
22 |
Var3 |
22 |
Var3 |
22 |
|
3 |
... |
00 |
... |
00 |
... |
00 |
... |
00 |
... |
00 |
|
4 |
Var4 |
44 |
Var4 |
44 |
Var4 |
44 |
Var4 |
44 |
Var4 |
44 |
|
5 |
Var5 |
55 |
Var5 |
55 |
||||||
|
6 |
... |
66 |
... |
66 |
Var5 |
55 |
||||
|
7 |
... |
77 |
... |
77 |
... |
66 |
||||
|
8 |
... |
88 |
... |
88 |
... |
77 |
Var5 |
55 |
Var5 |
55 |
|
9 |
Var6 |
99 |
Var6 |
99 |
... |
88 |
... |
66 |
... |
66 |
|
10 |
Var7 |
AA |
Var7 |
AA |
Var6 |
99 |
... |
77 |
... |
77 |
|
11 |
Var8 |
AA |
Var8 |
AA |
Var7 |
AA |
... |
88 |
... |
88 |
|
12 |
... |
00 |
... |
00 |
Var8 |
AA |
Var6 |
99 |
Var6 |
99 |
|
13 |
... |
00 |
... |
00 |
... |
00 |
Var7 |
AA |
Var7 |
AA |
|
14 |
... |
00 |
... |
00 |
... |
00 |
||||
|
15 |
... |
00 |
||||||||
|
16 |
Var8 |
AA |
Var8 |
AA |
||||||
|
17 |
... |
00 |
... |
00 |
||||||
|
18 |
... |
00 |
... |
00 |
||||||
|
19 |
... |
00 |
... |
00 |
||||||
|
20 |
||||||||||
|
21 |
||||||||||
|
22 |
||||||||||
|
23 |
||||||||||
|
24 |
||||||||||
|
25 |
||||||||||
|
26 |
||||||||||
|
27 |
||||||||||
|
28 |
||||||||||
|
29 |
||||||||||
|
30 |
||||||||||
|
31 |
||||||||||
示例 3
示例
STRUCT Var1 : BYTE := 16#01; Var2 : LWORD := 16#11; Var3 : BYTE := 16#22; Var4 : BYTE := 16#44; Var5 : DWORD := 16#88776655; Var6 : BYTE := 16#99; Var7 : BYTE := 16#AA; Var8 : WORD := 16#AA; END_TYPE
|
pack_mode = 0 |
pack_mode = 1 |
pack_mode = 2 |
pack_mode = 4 |
pack_mode = 8 |
||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
可变 |
数值 |
可变 |
数值 |
可变 |
数值 |
可变 |
数值 |
可变 |
数值 |
|
|
0 |
Var1 |
01 |
Var1 |
01 |
Var1 |
01 |
Var1 |
01 |
Var1 |
01 |
|
1 |
Var2 |
11 |
Var2 |
11 |
||||||
|
2 |
... |
00 |
... |
00 |
Var2 |
11 |
||||
|
3 |
... |
00 |
... |
00 |
... |
00 |
||||
|
4 |
... |
00 |
... |
00 |
... |
00 |
Var2 |
11 |
||
|
5 |
... |
00 |
... |
00 |
... |
00 |
... |
00 |
||
|
6 |
... |
00 |
... |
00 |
... |
00 |
... |
00 |
||
|
7 |
... |
00 |
... |
00 |
... |
00 |
... |
00 |
||
|
8 |
... |
00 |
... |
00 |
... |
00 |
... |
00 |
Var2 |
11 |
|
9 |
Var3 |
22 |
Var3 |
22 |
... |
00 |
... |
00 |
... |
00 |
|
10 |
Var4 |
44 |
Var4 |
44 |
Var3 |
22 |
... |
00 |
... |
00 |
|
11 |
Var5 |
55 |
Var5 |
55 |
Var4 |
44 |
... |
00 |
... |
00 |
|
12 |
... |
66 |
... |
66 |
Var5 |
55 |
Var3 |
22 |
... |
00 |
|
13 |
... |
77 |
... |
77 |
... |
66 |
Var4 |
44 |
... |
00 |
|
14 |
... |
88 |
... |
88 |
... |
77 |
... |
00 |
||
|
15 |
Var6 |
99 |
Var6 |
99 |
... |
88 |
... |
00 |
||
|
16 |
Var7 |
AA |
Var7 |
AA |
Var6 |
99 |
Var5 |
55 |
Var3 |
22 |
|
17 |
Var8 |
AA |
Var8 |
AA |
Var7 |
AA |
... |
66 |
Var4 |
44 |
|
18 |
... |
00 |
... |
00 |
Var8 |
AA |
... |
77 |
||
|
19 |
... |
00 |
... |
88 |
||||||
|
20 |
Var6 |
99 |
Var5 |
55 |
||||||
|
21 |
Var7 |
AA |
... |
66 |
||||||
|
22 |
Var8 |
AA |
... |
77 |
||||||
|
23 |
... |
00 |
... |
88 |
||||||
|
24 |
Var6 |
99 |
||||||||
|
25 |
Var7 |
AA |
||||||||
|
26 |
Var8 |
AA |
||||||||
|
27 |
... |
00 |
||||||||
|
28 |
||||||||||
|
29 |
||||||||||
|
30 |
||||||||||
|
31 |
||||||||||
无数据包模式下的行为
如果不使用打包模式,编译器通常会根据设备描述使用打包模式 4 或 8。在每种情况下,都会使用对处理器特别有利的打包模式,以便进行内存访问。这也被称为自然对齐或数据自然对齐。
使用背包模式时的负面效果
不对齐内存访问可能是使用属性'pack_mode' 的结果。举例来说,这意味着大小为 4 字节的数据类型会被定位在一个不能被 4 整除的地址上。通常情况下,在 32 位系统中,32 位数据类型的读写只需一次内存访问。在某些平台(例如
ARM 平台)上,只有当该值在内存中对齐时才有可能这样做。在其他平台上,访问是可能的,但速度要慢得多。
示例
{attribute 'pack_mode':=1}
TYPE DUT
STRUCT
by1 : BYTE;
dw1 : DWORD;
END_STRUCT
END_TYPE
在 ARM 平台上,无法通过单次访问读取dw1 的值。当试图直接访问该元素时,ARM 处理器将抛出异常。
假设执行以下读取访问: dwTest := dut1.dw1;
在访问DWORD dw1 时,需要进行四次内存访问,因为每个字节都要单独读取、移位和拆分。流程与下面的示例大致相同,在这个示例中,一个DWORD 由四个字节组成的数组生成:
dwHelp := bytes[0]; dwResult := dwHelp; dwHelp := bytes[1]; dwHelp := SHL(dwHelp, 8); dwResult := dwResult OR dwHelp; dwHelp := bytes[2]; dwHelp := SHL(dwHelp, 16); dwResult := dwResult OR dwHelp; dwHelp := bytes[3]; dwHelp := SHL(dwHelp, 24); dwResult := dwResult OR dwHelp;
显然,这种访问比访问DWORD 要慢得多,因为 在内存中已适当对齐。
pdw := ADR(dut1.dw1); dwTest := pdw^;
不过,当通过指针访问此类成员时,编译器不会生成访问示例。这意味着在 ARM 平台上,以下代码会导致异常。
pdw := ADR(dut1.dw1); dwTest := pdw^;
因此,出于性能考虑,应避免使用非自然对齐的结构。
打包结构不得包含未打包结构。