该 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^;
因此,出于性能考虑,应避免使用非自然对齐的结构。
打包结构不得包含未打包结构。