FOR loop
Syntax
FOR <loop_var> := <start_expr> TO <end_expr> [BY <step_expr>] DO
<statement_list>
END_FOR;
<loop_var>is an existing integer variable. ST does not let you declare it inline (unlike C++for (int i...).<start_expr>and<end_expr>must be integer expressions of the same type as<loop_var>.<step_expr>is optional; defaults to+1. Must be of the same type as<loop_var>and may be negative.
Semantics
Per IEC 61131-3 clause 6.6.3.4:
- Evaluate
<start_expr>,<end_expr>,<step_expr>once. Subsequent changes to those source expressions inside the body have no effect on the loop bounds. - Set
<loop_var>to the start value. - If
<step_expr> >= 0and<loop_var> > <end_expr>, exit. If<step_expr> < 0and<loop_var> < <end_expr>, exit. - Run the body.
<loop_var> := <loop_var> + <step_expr>.- Goto step 3.
The loop variable is not valid after the loop ends. The
last value depends on the implementation; matiec leaves it
at end + step.
Examples
(* Sum an array *)
iSum := 0;
FOR i := 1 TO 10 DO
iSum := iSum + arr[i];
END_FOR;
(* Reverse iteration *)
FOR i := 10 TO 1 BY -1 DO
arr[11 - i] := arr[i];
END_FOR;
(* Skip every second *)
FOR i := 0 TO 100 BY 2 DO
arrEven[i / 2] := arr[i];
END_FOR;
(* Early exit on found *)
iFound := -1;
FOR i := 0 TO 99 DO
IF arr[i] = TARGET THEN
iFound := i;
EXIT;
END_IF;
END_FOR;
Scan-cycle warning
A FOR i := 1 TO 1000 DO that does substantial work per
iteration easily eats your scan cycle. Cap the loop length
at compile time, profile the body, and split into per-cycle
chunks if needed (use a persistent counter variable that the
POU advances by N per scan).
IEC reference
IEC 61131-3 third edition (2013), clause 6.6.3.4 — “FOR statement”.
matiec conformance
matiec implements FOR per the standard. The three pitfalls
in llm_signals are real and reproducible:
- Type-strict bounds (no auto-promotion).
- Silent zero-iteration when BY sign and start/end direction disagree.
- Need for explicit
BY -1when iterating downward.