如果我们将ABAP字段符号和数据引用与C中的指针进行比较,我们观察到: -
在C中,假设我们声明一个变量"var"类型"integer",其默认值为"5".
变量"var"将存储在内存中的某些位置,并且表示保存此变量的内存地址为"1000".
现在我们定义一个指针"ptr",并将此指针赋给我们的变量.
因此,"ptr"将为"1000","*ptr"将为5.
让我们比较ABAP中的上述情况.
这里我们声明一个Field符号"FS"并将其赋值给变量"var".
现在我的问题是"FS"是什么?我在互联网上严格搜索过,但发现许多ABAP顾问认为FS持有变量的地址,即1000.但这是错误的.调试时我发现fs只有5个.所以fs(在ABAP中)相当于*ptr(在C中).如果我的理解是错误的,请纠正我.
现在让我们声明一个数据引用"dref"和另一个字段符号"fsym",在创建数据引用后,我们将它们分配给字段符号.现在我们可以对这个字段符号进行操作.所以数据引用和字段符号之间的区别是: -
在字段符号的情况下,我们将声明一个变量并将其分配给字段符号.
在数据引用的情况下,我们首先获取数据引用,然后将其分配给字段符号.
那么数据引用的用途是什么?我们可以通过字段符号实现相同的功能.
小智 16
字符符号很像指针,但只能以解除引用的形式访问.换句话说,它将在内部保存分配给它的变量的内存地址,但它不允许您查看内存地址,只允许查看存储在它指向的变量中的数据.这可以证明,因为如果更改指向内部表格行的字段符号的内容,您将看到更改将直接在该行中进行.
数据引用就像一个简单的指针,除了你不能像C中那样增加或减少内存地址(ptr ++,ptr--等等).它与字段符号不同,因为您可以比较两个数据引用以检查它们是否指向内存中的完全相同的位置.比较两个字段符号将是一个简单的值比较.另一个区别是您可以使用CREATE DATA命令通过创建数据引用来动态分配内存.字段符号只能分配给已分配的变量.
尽管数据引用和字段符号看起来非常相似并且通常以相似的方式使用(请参阅其他答案),但它们本质上是不同的。
数据引用是存储值的变量,就像字符串或整数一样。它们具有固定的内存大小和内容。唯一的区别是这些引用是指向其他数据对象的指针,即内容具有特殊含义。它们不能指向任何地方,它们可以被取消引用,您可以将它们传递给其他例程,您可以操作指针(GET REFERENCE)或其指向的值。实际上,它没什么特别的——只是你从你最喜欢的编程语言中知道的指针。
字段符号不是“真正的”变量。该文档指出
他们没有为场地实际预留空间
字段符号实际上只是ABAP VM本地符号表的巧妙操作。我将尝试说明这一点 - 请注意,这是一个高度简化的模型。假设您声明了三个变量:
DATA: my_char TYPE c,
my_int TYPE i,
my_ref TYPE REF TO i.
Run Code Online (Sandbox Code Playgroud)
然后符号表将包含 - 除其他外 - 可能如下所示的条目:
name type size addr
------------------------------
MY_CHAR c 1 0x123456
MY_INT i 4 0x123457
MY_REF r ? 0x123461
Run Code Online (Sandbox Code Playgroud)
(我不确定引用变量的实际大小。)
这些条目仅指向包含这些值的地址。根据这些变量的范围,它们可能驻留在完全不同的内存区域,但这不是我们目前关心的问题。重点是:
让我们添加一个字段符号:
FIELD-SYMBOLS: <my_fs> TYPE any.
Run Code Online (Sandbox Code Playgroud)
那么该符号可能如下所示:
name type size addr target
--------------------------------------
MY_CHAR c 1 0x123456
MY_INT i 4 0x123457
MY_REF r ? 0x123461
<MY_FS> *
Run Code Online (Sandbox Code Playgroud)
字段符号在其初始状态(未分配)下创建。它不指向任何地方,在这种状态下使用它会导致短转储。重要的一点是:它不像其他变量那样由“堆”内存支持。让我们
ASSIGN my_char TO <my_fs>.
Run Code Online (Sandbox Code Playgroud)
该符号可能再次如下所示:
name type size addr target
--------------------------------------
MY_CHAR c 1 0x123456
MY_INT i 4 0x123457
MY_REF r ? 0x123461
<MY_FS> * MY_CHAR
Run Code Online (Sandbox Code Playgroud)
现在,当访问 时<my_fs>,运行时系统会将其识别为字段符号,在符号表中查找当前目标并将所有操作重定向到 的实际位置my_char。另一方面,如果您发出命令
GET REFERENCE OF my_int INTO my_ref.
Run Code Online (Sandbox Code Playgroud)
符号表不会改变,但在“堆地址”0x123461处,你会找到“地址”0x123457。my_char = 'X'只是一个像or 这样的赋值my_int = 42 * 2。
在一个非常简化的版本中,这就是为什么您不能将字段符号作为更改参数传递并允许它们在子例程内重新分配的原因。它们的存在方式与其他变量不同,并且它们在添加到的符号表范围之外没有任何意义。