SAP ABAP 里的隐藏数据类型:%_c_pointer

文摘   2024-11-13 18:28   北京  

使用 ABAP Development Tool 的源代码搜索功能,搜索关键字 %_c_pointer, 能搜出很多结果:

具有这种百分号开头的数据类型的 ABAP 变量,无一例无的都用于 ABAP 框架实现里,并且均参与了 System Call 或者 Kernel Module 调用。

关于 ABAP System Call 和 Kernel Module 调用,请参阅笔者之前的文章:

所以 %_c_pointer 到底描述了何种数据类型?

或许我们可以从一个定义了该类型的 ABAP 类属性的描述信息里,挖掘一点端倪:Decompress Handle.

Handle 是计算机编程领域里使用及其广泛的一个术语,中文翻译成句柄

计算机系统在程序设计中涉及多种硬件和软件资源,例如文件、内存块、图形对象、进程线程等。

这些资源既需访问,也需有效管理。然而,这些资源的管理往往相当复杂且易出错,因为它们直接关联底层的物理或逻辑组件,例如磁盘的特定扇区或者内存的某个地址空间。

为了处理这种复杂性,handle 作为一个中间层次的抽象角色,为资源管理和使用带来了极大的简化。

Handle 本质上是一个抽象引用,作为一种间接的标识符,用于让操作系统或运行时环境,找到真实资源的引用。当程序想要操作某一特定资源时,它通过 handle 向操作系统或者管理资源的 API 发出请求,操作系统或者 API 负责管理资源的细节。

比如上图 CL_ABAP_UNGZIP_BINARY_STREAM 类,负责对二进制流进行解压操作。句柄 DS 指向待操作的二进制流,配合其方法 DECOMPRESS_BINARY_STREAM 对这些流进行解压操作。

通过抽象的句柄,为 ABAP 开发人员屏蔽了流的底层存储方式和操作手段等技术实现细节。

同样,%_c_pointer 名称里带有的 pointer,让我们不禁思考,是否这个类型同 C 语言的指针有某种联系?

实际上,它就是 C 语言里一种特殊类型的指针,即指向指针的指针

我们在 ABAP 帮助文档里进行搜索,就可以找到 ABAP 数据类型 %_c_pointer 在 C 语言里的对应类型:void**.

从上图这张表里,大家还能发现 ABAP 泛型编程里常用的 DATA,ANY, SIMPLE 等数据类型,对应着 C 语言里的 void*.

那么 void, void* 和 %_c_pointer 对应的 void**, 各自的含义是什么?

void 是 C 语言中的一种特殊类型,表示无类型或无返回值

void 具有多种用途,其语义在不同上下文中会有所变化。

  • 用作函数的返回类型:表示该函数不返回任何值。例如

void printMessage() {   printf("Hello, World!\n");}

相当于 ABAP Function Module 没有定义 EXPORTING 或者 RETURNING 参数。

void 告诉编译器,这个函数只执行某种操作,而不需要返回数据。

  • 用作函数的参数列表:当函数的参数部分定义为 void 时,表示该函数不接受任何参数。例如:

void doSomething(void) {   // 这里的代码不需要任何输入参数}

相当于 ABAP Function Module 里没有定义任何 IMPORTING 或者 CHANGING 参数。

void* 是 C 语言中的通用指针或无类型指针。

它可以指向任何数据类型,而不要求明确指明所指向的数据类型。

例如开发人员可以将 int,float,或者 struct 的地址赋值给一个 void* 类型的指针。

int a = 10;
void* p = &a; // void* 指向一个 int 类型的数据

void* 在 C 语言中有着重要的地位,尤其是在实现通用的函数库或处理不同类型的数据时。例如,标准库函数 malloc 使用 void* 返回指向新分配内存的指针:

void* ptr = malloc(100); // 分配 100 字节的内存

在这种场景下,malloc 不知道调用者希望将这块内存用于哪种类型的数据,因此它返回一个 void*.

调用者可以根据需要将这个指针转换为其他具体类型的指针。

因此有 C 语言使用 void* 基础的开发人员,转 ABAP 开发时,对于 DATA,ANY 等关键字的理解,可以说是轻松愉快。

void** 是一个指向 void* 类型数据的指针,也就是说,它是指向指针的指针,即多级指针

以下是一个例子:

int a = 10;
void* p = &a; // p 是一个 void*,指向 int 类型的数据
void** pp = &p; // pp 是一个 void**,指向 p

在这个例子中,pp 是一个指向 p 的指针。而 p 本身是一个 void*,指向整数 a.

因此,void** 实际上是用来间接访问某个指针的。

这可以类比为一份地图。假设地图 pp 指向另一份地图 p,而 p 最终指向目标地点 a.

void** 就是这样的地图,提供一种间接查找最终地址的能力。

可以用下面的 ABAP 代码来近似模拟 C 语言里多级指针的例子。

DATA: lv_i TYPE int4 VALUE 1.
DATA(void*) = REF #( lv_i ).
DATA(void**) = REF #( void* ).
WRITE: void**->*->*.

这里的变量 void*, 是一个指向整数 1 的引用,而变量 void**, 是指向该引用的引用。

ABAP 里的引用变量和 Field Symbol 结合起来,实现了 C 语言里指针的功能。

下图中的代码显示,* 也是 ABAP 变量名的一部分,这种命名方式合法,但是并不推荐,因为会给代码阅读者带来不必要的麻烦。

笔者在之前的文章里有详细介绍:

那些令人哭笑不得,看了想揍人的 ABAP 变量命名方式,强烈不推荐

如果大家即使阅读了本文之后,对于 %_c_pointer 的含义仍然感到困惑,也没有关系。

因为这个数据类型,不会在应用层面的开发中使用到。

码农干货铺
永远要保持一种无论何时何地都逼着自己更努力更优秀来享受更好生活的学习状态
 最新文章