PLC Structured Text Object Oriented Programming
PLC结构化文本(ST)——指针和引用(Pointer&Reference)
指针的定义
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。---C++ 指针|菜鸟教程
解释一下这里为什么不继续引用C#和Java的定义,因为C#和Java明确删除了指针,所以找不到关于指针的介绍。
引用的定义
引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。---C++ 引用|菜鸟教程
指针与引用的区别
引用很容易与指针混淆,它们之间有三个主要的不同:
- 不存在空引用。引用必须连接到一块合法的内存。
- 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
- 引用必须在创建时被初始化。指针可以在任何时间被初始化。
---C++ 引用 vs 指针
指针的使用
在程序(PRG)中声明整型(INT)变量'in01',再声明指针变量指向INT类型。
PROGRAM Main
VAR
in01 : INT;
pint : POINTER TO INT;
END_VAR
在代码编辑区使用取址运算符获取变量“ in01 ”的内存地址赋值给指针变量“ pint ”,然后对指针变量解除地址引用赋值44,最终变量in01当前值为44。
pint := ADR(in01);
if pint<>0 then
pint^ := 44;
END_IF
引用的使用
PROGRAM Main
VAR
in01 : INT;
refint : REFERENCE TO INT;
END_VAR
------------
refint REF= in01;
if __ISVALIDREF(refint) then
refint := 11;
END_IF
在代码编辑区引用类型变量refint使用REF=运算符与整型变量in01建立引用关系,然后将refint赋值11,最终变量in01当前值为11。
Tips : 某些情况下会存在空引用,所以在使用REFERENCE引用类型时,一般做有效引用的判断运算符 __ISVALIDREF,若引用对象不为空则返回TRUE,若为无效引用则返回FALSE。
指针实现Fluent
- 创建 FB_StringBuilder 功能块
FUNCTION_BLOCK FB_StringBuilder
VAR
sContent : STRING;
END_VAR
- 实现 Append 方法,返回指针类型指向 FB_StringBuilder
METHOD Append : POINTER TO FB_StringBuilder
VAR_INPUT
sText : STRING;
END_VAR
-------------------
sContent := CONCAT(STR1 := sContent, STR2 := sText);
Append := THIS; // THIS指针指向自身实例对象
- 实现 Clear 方法,返回指针类型指向 FB_StringBuilder
METHOD Clear : POINTER TO FB_StringBuilder
VAR_INPUT
END_VAR
------------------
sContent := '';
Clear := THIS; // THIS指针指向自身实例对象
- 实现 ToString 方法,返回STRING类型
METHOD ToString : STRING
VAR_INPUT
END_VAR
------------------
ToString := sContent;
- Main函数声明及调用
PROGRAM MAIN
VAR
// 输出'Hello world'
fbStringBuilder : FB_StringBuilder;
sResult : STRING;
bTest : BOOL;
END_VAR
------------------
IF bTest THEN
sResult := fbStringBuilder.Clear()^
.Append('H')^
.Append('e')^
.Append('l')^
.Append('l')^
.Append('o')^
.Append(' ')^
.Append('W')^
.Append('o')^
.Append('r')^
.Append('l')^
.Append('d')^
.ToString();
bTest := FALSE;
END_IF
使用指针也能实现“ Fluent ”效果,只是看起来一点都不优雅。
引用实现Fluent
- 创建 FB_StringBuilder 功能块
FUNCTION_BLOCK FB_StringBuilder
VAR
sContent : STRING;
END_VAR
- 实现 Append 方法,返回引用类型 FB_StringBuilder
METHOD Append : REFERENCE TO FB_StringBuilder
VAR_INPUT
sText : STRING;
END_VAR
-------------------
sContent := CONCAT(STR1 := sContent, STR2 := sText);
Append REF= THIS^;
- 实现 Clear 方法,返回引用类型 FB_StringBuilder
METHOD Clear : REFERENCE TO FB_StringBuilder
VAR_INPUT
END_VAR
------------------
sContent := '';
Clear REF= THIS^;
- 实现 ToString 方法,返回STRING类型
METHOD ToString : STRING
VAR_INPUT
END_VAR
------------------
ToString := sContent;
- Main函数声明及调用
PROGRAM MAIN
VAR
// 输出'Hello world'
fbStringBuilder : FB_StringBuilder;
sResult : STRING;
bTest : BOOL;
END_VAR
------------------
IF bTest THEN
sResult := fbStringBuilder.Clear()
.Append('H')
.Append('e')
.Append('l')
.Append('l')
.Append('o')
.Append(' ')
.Append('W')
.Append('o')
.Append('r')
.Append('l')
.Append('d')
.ToString();
bTest := FALSE;
END_IF
使用REFERENCE类型实现“ Fluent ”效果。综合比较实现流式编程使用引用(REFERENCE)或者接口(INTERFACE) 效果会更好,编码便捷。
总结
指针就是地址,引用是对指针的包装,指针容易出现空指针,引用相对更安全,但仍需要注意出现空引用的情况。
这是目前IEC61131-3标准中我能想到的实现“Fluent”三种编程方式。若还有其它我不知道的方法,欢迎大神留言讨论。