Pointers and references are both powerful features in TwinCAT 3 that allow for efficient memory management and manipulation of data. However, they have distinct differences that are important to understand when designing and implementing your code. This blog article will give you a brief overview of the definition, the advantages and disadvantages of pointers and references, and which application they are best suited for. The following examples, made for TwinCAT 3, should clarify the choice.
Why should we use it?
A pointer or reference is stored in as many bytes as it takes to hold an address on the computer. This often makes them much smaller than the things they point to. We take advantage of this small size when storing data and when passing parameters to functions. It is much faster and more memory-efficient to copy a pointer or a reference than to copy many of the things they are likely to point to.
Naked facts about pointers
A pointer is a variable that holds the memory location of another variable.
The pointer variable returns the value located at the address stored in the pointer variable which is preceded by the pointer sign ‚^‘.
Operators in TwinCAT:
^
,ADR()
The pointer variable can refer to NULL.
An uninitialized pointer can be created.
The pointer variable can be initialized at any point of time in the program.
The pointer variable can be reinitialized as many times as needed.
The result of the difference between two pointers is of type DWORD, even on 64-bit platforms if the pointers are 64-bit pointers.
UNCTION CheckPointer
Implementation example of FUNCTION CheckPointer
: https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/2530405259.html&id=
Naked facts about references
The reference variable is used to refer to the variable which is assigned to that reference variable.
The reference variable returns the address of the variable.
Operators in TwinCAT:
REF=
or:=
An exception to this is when an input is a “REFERENCE TO” and the input is transferred within the call. In this case, the normal allocation operator :=
is used instead of the allocation operator REF=
.
The reference variable can never refer to NULL.
An uninitialized reference can never be created.
The reference variable can only be initialized at the time of its creation.
The reference variable can never be reinitialized again in the program.
Check functions: use operator
__ISVALIDREF
Implementation example of operator __ISVALIDREF
: https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/2529458827.html&id=
How to use pointers in TwinCAT 3
In TwinCAT3, pointers are declared using the „POINTER TO“ keyword, followed by the data type of the variable that the pointer points to. For example, to create a pointer to an integer variable, you would use the following syntax:
To assign the memory address of a variable to a pointer, use the „ADR“ operator. For example, to assign the memory address of the variable „myVar“ to the pointer „myPointer“, you would use the following code:
To access the value of the variable that a pointer points to, you use the „^“ operator. For example, to access the value of the variable „myVar“ using the pointer „myPointer“, you would use the following code:
How to use references in TwinCAT 3
References, on the other hand, are declared using the „REFERENCE TO“ keyword, followed by the data type of the variable that the reference refers to. For example, to create a reference to an integer variable, you would use the following syntax:
For assignments in the code body (not calls) use the “REF=” assignment. For example, to assign the variable „myVar“ to the reference „myReference“, you would use the following code:
To access the value of the variable that a reference refers to, you use the variable name without an additional operator. For example, to access the value of the variable „myVar“ using the reference „myReference“, you would use the following code:
Use cases and code examples
Demonstration of the type independence of pointers compared to references
Pointers used for dynamic arrays
It is important to make sure to de-allocate memory for dynamic arrays after using them, to avoid memory leaks.
Pointer arithmetic example
Note that incrementing a pointer that contains a null pointer value is strictly undefined behavior. Normally, you should only use increment/decrement when pointing to elements of an array.
Reference use case: Pass input signal by references via FB_INIT
into a class
At the outside of the simple senor class the hardware input is assigned to the reference “di_Sensor”:
In the FB_INIT
of the simple sensor the reference is referenced to the sensor input variable of the class:
A reference always needs to be initialized with a variable! The variable must exist before the reference will be initialized with this variable!
Inside of the class, you can use the input value of the sensor signal like every other common data type without address operator or de referencing:
So far, so good! But when do I use what?
Advantages of pointers
Null-ability: Pointers can be set to the null value, whereas references cannot. This allows for more flexibility in situations where a variable may or may not be present.
Aliasing: Pointers can point to different variables at different times, whereas references are bound to a specific variable and cannot be reassigned. This can be useful when working with complex data structures and performing operations on multiple variables at the same time.
Dynamic memory allocation: Pointers can be used to dynamically allocate memory on the heap, while references cannot. This allows for more dynamic and flexible use of memory in situations where the amount of memory required may not be known at compile time.
Pointers are more efficient for passing large data structures to a function by reference.
Pointers can also be used to create linked data structures such as linked lists and trees. This is not possible with references.
Advantages of references
Easier to use: The reference does not have to be de-referenced (with ^) to access the contents of the referenced object.
Cleaner syntax for transferring values: If an input is a “REFERENCE TO”, there is no need to write
ADR(value)
at a(refInput := value)
.Type safety: In contrast to pointers, for references the compiler checks whether the base type is the same when assigning two references. (Please note that for pointers this check can be performed using the compiler extension TE1200 Static Analysis. See rule SA0019.)
Conclusion
The biggest difference between pointers and references is that pointers are way more powerful than references but less safe to use. With pointers you can do a lot more things, like working with dynamic storage and arithmetic calculations. Also, pointers are not type-related, which is useful when you are calculating with stings. However, it is important to note that pointers are generally considered more error-prone than references, as they can be de-referenced improperly, leading to undefined behavior or memory access violations. Also, references are safer to use because they cannot be null, and their type is known at compile time. In general, it is recommended that references be used in most cases. Pointers should be reserved for special cases where their advantages outweigh their disadvantages.
Here you will find more about pointers in TwinCAT: https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/2529453451.html&id=
Here you can learn more about references in TwinCAT: https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/2529453451.html&id=
For more insights on this topic, check out our in-depth video on pointers and references on YouTube here.