You can bound a variable of the integer type into the predefined range. In other words you can set the low limit and the hi limit for the integer variable. Thus you can create a new integer type. But is it realy?
Actual for the following types only: SINT, USINT, INT, UINT, DINT, UDINT, BYTE, WORD, DWORD, LINT, ULINT, LWORD.
Let's play in the sandbox. For the clarity, I have used underscores in the names of subrange variables.
You can do same actions with a variable of subrange type as with a variable of an integer type. In fact, this is not a new data type with a new bounds (or restrictions), but it is a suggestion or a clue to the compiler how to check some cases (I will discuss it later) or how to control variable value.
Possible:
Are not allowed:
So I decided to check whether or not someone controls the output of the variable value for the specified range during the operation process. I wrote zero to the variable `value` through the pointers. And zero was recorded (nothing bad happened). And then I have added 1 to the variable and suddenly, the value of the variable increased by 1. Where is the bounds?
In general, if we performe cyclically _value_ := _value_ + 1; we will see the whole range of INT values from -32768 to +32767, without any restrictions from the runtime system.
Conclusion: the runtime does not control the value of the variable; it works like a regular integer type, and nothing else.
There is a whole family of POUs for implicit checks of the variable value (e.g. division by zero checks POUs):
You have to add some special POUs to the project to control data bounds during the execution:
...then choose L|Range Checks and finally rebuild project. Newcome POUs will control the variable and limits it if the value overstep the bounds defined by you. And now if you repeat the last used trick with pointers but with already activated implicit checking you can get completely different result. Runtime system will call corresponding POU that will limit variable to the predefined bounds.
FYI, performance measurements are performed to catch whether additional work is happening behind the scenes or not. There was no point in optimizing for 1-2 nanoseconds, although who knows what's going on there. Vertical axis in hundreds of nanoseconds: 83000 = 8.3 milliseconds.
Testing ground:
Without POUs for implicit checks:
Added POUs for implicit checks then the project was rebuilt:
Conclusion: POUs for implicit checks cause extra load.
Let's play in the sandbox. For the clarity, I have used underscores in the names of subrange variables.
You can do same actions with a variable of subrange type as with a variable of an integer type. In fact, this is not a new data type with a new bounds (or restrictions), but it is a suggestion or a clue to the compiler how to check some cases (I will discuss it later) or how to control variable value.
Unfortunately, you cannot do this: _analog_ : REAL (4.0 .. 20.0); and it is not about too many dots in a row but because of the inaccuracy of the floating-point types.
Truth Or Dare
Possible:
Are not allowed:
Excavating Memory
So I decided to check whether or not someone controls the output of the variable value for the specified range during the operation process. I wrote zero to the variable `value` through the pointers. And zero was recorded (nothing bad happened). And then I have added 1 to the variable and suddenly, the value of the variable increased by 1. Where is the bounds?
In general, if we performe cyclically _value_ := _value_ + 1; we will see the whole range of INT values from -32768 to +32767, without any restrictions from the runtime system.
Conclusion: the runtime does not control the value of the variable; it works like a regular integer type, and nothing else.
Implicit Checks
There is a whole family of POUs for implicit checks of the variable value (e.g. division by zero checks POUs):
You have to add some special POUs to the project to control data bounds during the execution:
...then choose L|Range Checks and finally rebuild project. Newcome POUs will control the variable and limits it if the value overstep the bounds defined by you. And now if you repeat the last used trick with pointers but with already activated implicit checking you can get completely different result. Runtime system will call corresponding POU that will limit variable to the predefined bounds.
Performance
FYI, performance measurements are performed to catch whether additional work is happening behind the scenes or not. There was no point in optimizing for 1-2 nanoseconds, although who knows what's going on there. Vertical axis in hundreds of nanoseconds: 83000 = 8.3 milliseconds.
Testing ground:
Without POUs for implicit checks:
Added POUs for implicit checks then the project was rebuilt:
Conclusion: POUs for implicit checks cause extra load.
Resume
- In fact, this is not a new data type, just an ordinary integer type (INT, BYTE, ...) with extra information about subrange.
- Range are clue for a compiler.
- Range controlled by extra POUs for implicit checks. This is optional.
- Implicit checks cause extra load because of execution extra POUs.