属性:pack_mode
pragma 定义了在分配期间如何打包数据结构。该属性必须插入到数据结构之上并影响整个结构的打包。
句法:
{attribute 'pack_mode' := ' <pack mode value> '}
插入位置:数据结构声明的上方
<pack mode value>
<打包模式值> | 相关包装方式 | 描述 |
---|---|---|
0 | 对齐 | 所有变量都分配给字节地址。没有记忆空白。 |
1 | 1 字节对齐 | |
2 | 2 字节对齐 | . 有
|
4 | 4 字节对齐 | . 有
|
8 | 8 字节对齐 | . 有
|
提示
根据结构的不同,各个模式的内存映射可能没有差异。例如,具有以下结构的内存分布 {attribute 'pack mode' := '4'}
pragma 可以对应于 {attribute 'pack mode' := '8'}
。
提示
结构数组
如果将结构组合成数组,则在结构的末尾添加字节,以便对齐下一个结构。
重要
如果 兼容性布局 在符号配置中选择了选项,同时属性 '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
在 0x0105
.
示例 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 = 8 | pack_mode = 0 | pack_mode = 1 | pack_mode = 2 | pack_mode = 4 | ||||||
---|---|---|---|---|---|---|---|---|---|---|
多变的 | 价值 | 多变的 | 价值 | 多变的 | 价值 | 多变的 | 价值 | 多变的 | 价值 | |
0 |
|
|
|
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
|
|
|
|
2 |
|
|
|
|
|
|
|
|
|
|
3 | … |
| … |
| … |
| … |
| … |
|
4 |
|
|
|
|
|
|
|
|
|
|
5 |
|
|
|
| ||||||
6 | … |
| … |
|
|
| ||||
7 | … |
| … |
| … |
| ||||
8 |
|
| … |
| … |
| … |
|
|
|
9 | … |
|
|
|
|
| … |
| … |
|
10 | … |
|
|
|
|
|
|
| … |
|
11 | … |
|
|
|
|
|
|
| … |
|
12 |
|
| … |
| … |
|
|
|
|
|
13 |
|
| … |
| … |
| … |
|
|
|
14 | … |
| … |
| … |
| ||||
15 | … |
| ||||||||
16 |
|
|
|
| ||||||
17 | … |
| … |
| ||||||
18 | … |
| … |
| ||||||
19 | … |
| … |
| ||||||
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 = 8 | pack_mode = 0 | pack_mode = 1 | pack_mode = 2 | pack_mode = 4 | ||||||
---|---|---|---|---|---|---|---|---|---|---|
多变的 | 价值 | 多变的 | 价值 | 多变的 | 价值 | 多变的 | 价值 | 多变的 | 价值 | |
0 |
|
|
|
|
|
|
|
|
|
|
1 |
|
|
|
| ||||||
2 | … |
| … |
|
|
| ||||
3 | … |
| … |
| … |
| ||||
4 | … |
| … |
| … |
|
|
| ||
5 | … |
| … |
| … |
| … |
| ||
6 | … |
| … |
| … |
| … |
| ||
7 | … |
| … |
| … |
| … |
| ||
8 |
|
| … |
| … |
| … |
| … |
|
9 | … |
|
|
|
|
| … |
| … |
|
10 | … |
|
|
|
|
|
|
| … |
|
11 | … |
|
|
|
|
|
|
| … |
|
12 | … |
| … |
| … |
|
|
|
|
|
13 | … |
| … |
| … |
| … |
|
|
|
14 | … |
| … |
| … |
| … |
| ||
15 | … |
|
|
|
|
| … |
| ||
16 |
|
|
|
|
|
|
|
|
|
|
17 |
|
|
|
|
|
|
|
| … |
|
18 | … |
| … |
|
|
| … |
| ||
19 | … |
| … |
| ||||||
20 |
|
|
|
| ||||||
21 | … |
|
|
| ||||||
22 | … |
|
|
| ||||||
23 | … |
| … |
| ||||||
24 |
|
| ||||||||
25 |
|
| ||||||||
26 |
|
| ||||||||
27 | … |
| ||||||||
28 | ||||||||||
29 | ||||||||||
30 | ||||||||||
31 |
没有的行为 'pack-mode'
如果 'pack-mode'
不使用,则编译器通常使用打包模式 4 或 8,具体取决于设备描述。在每种情况下,都使用对处理器特别有利的打包模式,以便可以执行内存访问。这也称为自然对齐或数据的自然对齐
使用时的负面影响 'pack-mode'
未对齐的内存访问可能是使用属性的结果 '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^;
因此,出于性能原因,您应该避免使用未自然对齐的结构。
压缩结构不得包含未压缩结构。