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”三種程式設計方式。若還有其它我不知道的方法,歡迎大神留言討論。