尽管数据引用和字段符号看起来非常相似并且经常以相似的方式使用(参见其他答案),但它们有着根本的不同。
数据引用是存储值的变量,就像字符串或整数一样。它们在内存中具有固定大小和内容。唯一的区别是这些引用是指向其他数据对象的指针,即内容具有特殊含义。它们不能指向任何地方,它们可以被取消引用,你可以将它们传递给其他例程,你可以操纵指针 ( GET REFERENCE
) 或它指向的值。它没有什么特别之处,真的 - 只是你最喜欢的编程语言中所知道的指针。
字段符号不是“真正的”变量。该文件指出
他们没有为一个字段物理保留空间
字段符号实际上只是对 ABAP VM的本地符号表的巧妙操作。我将尝试说明这一点 - 请注意,这是一个高度简化的模型。假设您声明了三个变量:
DATA: my_char TYPE c,
my_int TYPE i,
my_ref TYPE REF TO i.
然后符号表将包含 - 除其他外 - 可能如下所示的条目:
name type size addr
------------------------------
MY_CHAR c 1 0x123456
MY_INT i 4 0x123457
MY_REF r ? 0x123461
(我不确定参考变量的实际大小。)
这些条目仅指向包含这些值的地址。根据这些变量的范围,它们可能驻留在完全不同的内存区域中,但这不是我们目前关心的问题。重点是:
- 必须为变量保留内存(这是自动完成的,即使是引用)。
- 引用就像所有其他变量一样工作。
让我们为此添加一个字段符号:
FIELD-SYMBOLS: <my_fs> TYPE any.
那么符号可能如下所示:
name type size addr target
--------------------------------------
MY_CHAR c 1 0x123456
MY_INT i 4 0x123457
MY_REF r ? 0x123461
<MY_FS> *
字段符号在其初始状态(未分配)中创建。它没有指向任何地方,在这种状态下使用它会导致短暂的转储。重要的一点是:它不像其他变量那样由“堆”内存支持。让我们
ASSIGN my_char TO <my_fs>.
同样,该符号可能如下所示:
name type size addr target
--------------------------------------
MY_CHAR c 1 0x123456
MY_INT i 4 0x123457
MY_REF r ? 0x123461
<MY_FS> * MY_CHAR
现在,当访问 时<my_fs>
,运行时系统会将其识别为字段符号,在符号表中查找当前目标并将所有操作重定向到 的实际位置my_char
。另一方面,如果您发出命令
GET REFERENCE OF my_int INTO my_ref.
符号表不会改变,但在“堆地址”0x123461,你会找到“地址”0x123457。my_char = 'X'
只是一个像or的赋值my_int = 42 * 2
。
这就是在一个非常简化的版本中,您不能将字段符号作为更改参数传递并允许它们在子例程中重新分配的原因。它们的存在方式与其他变量不同,并且它们在被添加到的符号表范围之外没有任何意义。