Problem Overview: GT_STRNG Compilation Failures in SCL
When engineers first use the GT_STRNG (greater-than string compare) function in Siemens SCL within TIA Portal, they frequently encounter a cluster of compiler errors on a single line. The typical failure pattern looks like this:
STRING_CRANE_VALUE := GT_STRNG(STRING_COMP1 := ' ', STRING_COMP2 := ' ');
The compiler then reports any combination of the following diagnostics on the offending line:
- "Invalid input, in/out, output parameter" (reported twice)
- "Invalid Assignment" (reported twice)
- "Invalid or missing function type"
These five errors on one line are not five independent faults; they are cascading symptoms of one or two underlying mistakes. The same error cluster appears whether the block is declared as a FUNCTION (FC) or a FUNCTION_BLOCK (FB), and it is independent of the STRING length used (e.g., STRING[1], STRING[2], or the default STRING[254]).
For background on how SCL expressions are constructed and how the compiler binds operands to operators, see the Siemens SCL Expressions and Operations reference in the TIA Portal help system.
Root Cause Analysis: Three Failure Modes
Across multiple reproductions of this error, the root cause always falls into one of three categories. Confirm each in order before changing any code.
Failure Mode 1 — Wrong Parameter Names
The single most common cause. SCL's named-parameter call syntax requires the parameter identifiers declared in the FC interface, not user-defined names. The interface of GT_STRNG in the standard library uses the formal parameters:
| Parameter | Direction | Type | Description |
|---|---|---|---|
S1 |
INPUT | STRING | First string operand |
S2 |
INPUT | STRING | Second string operand |
| Return value | RET_VAL | BOOL | TRUE if S1 > S2 (ASCII order) |
Writing STRING_COMP1 := ... or any other custom name causes the compiler to reject both bindings, then to flag the assignment to STRING_CRANE_VALUE as invalid, and finally to declare the function type itself invalid because no valid call could be resolved. Five errors from one mistake.
Failure Mode 2 — Wrong FC Number
The standard GT_STRNG is FC15 in the SIMATIC S7-1200/1500 standard library. A closely named neighbour, FC16 (I_STRNG, integer-to-string conversion), has a completely different interface. If the symbol table or program element is dragged from a different category, FC16 can be silently substituted, producing the same error cluster because I_STRNG takes an integer input, not a string.
Failure Mode 3 — Interface Declaration Mistakes
Two specific declaration patterns trigger the error:
- Declaring the FC as
FUNCTION FC16 : BOOL(i.e., naming the wrong FC, see Mode 2). - Declaring
FUNCTION FC100 : BOOLcorrectly but withVAR_INPUTparameters of typeSTRING(no length) when the call site passesSTRING[1]— although this typically produces a warning, not the five-error cluster, it can mask Mode 1.
Correct GT_STRNG Syntax in SCL
The corrected function (FC) declaration that compiles cleanly:
FUNCTION FC100 : BOOL
VAR_INPUT
String_Comp1 : STRING;
String_Comp2 : STRING;
END_VAR
BEGIN
FC100 := GT_STRNG(S1 := String_Comp1, S2 := String_Comp2);
END_FUNCTION
The corrected function block (FB) declaration:
FUNCTION_BLOCK FB100
VAR_INPUT
String_Comp1 : STRING[1];
String_Comp2 : STRING[2];
END_VAR
VAR_OUTPUT
STRING_CRANE_VALUE : BOOL;
END_VAR
BEGIN
STRING_CRANE_VALUE := GT_STRNG(S1 := String_Comp1, S2 := String_Comp2);
END_FUNCTION_BLOCK
Note the structural differences between an FC and an FB:
| Feature | FUNCTION (FC) | FUNCTION_BLOCK (FB) |
|---|---|---|
| Return value | Yes (declared after FC name) | No |
| Instance DB | Not required | Required for static data |
| Result delivery | Function name acts as implicit return | Must use VAR_OUTPUT |
| Local memory | Temporary (L stack only) | Persistent in instance DB |
| Multiple calls | Each call has independent temporaries | Each instance DB is independent |
For a deeper walkthrough of creating the block, defining the interface, and entering SCL code in TIA Portal, see Writing your first SCL Code in TIA Portal (note: third-party tutorial, treat as supplementary reference, not an official Siemens manual).
STRING Data Type Details for SCL
The STRING type in S7-1200/1500 is not a C-style null-terminated array. It is a structured type with two internal fields:
| Component | Type | Meaning |
|---|---|---|
| String header (bytes 0–1) | WORD / INT | Maximum length (only the low byte is used in S7-1200) |
| Actual length (byte 2) | BYTE / USINT | Current valid character count |
| Characters (bytes 3 onward) | BYTE array | ASCII payload, left-justified |
When you declare STRING[1], the compiler reserves the 2-byte header plus 1 character (3 bytes total). STRING[2] reserves 4 bytes, and the default STRING without a length specifier is 254 characters (256 bytes total).
Critical detail for GT_STRNG: the comparison is performed using the actual length and the character codes in left-to-right ASCII order. A single-character STRING[1] holding the character '@' (ASCII 64) compares correctly against '!' (ASCII 33) and '%' (ASCII 37). Padding characters beyond the actual length are not inspected.
Field-Example: Crane Identifier Discrimination
A common industrial use case is discriminating between two crane IDs encoded as the first character of a STRING tag. Suppose the data block DB_CraneID contains a STRING[1] tag that will hold either '!' (ASCII 33, crane A) or '@' (ASCII 64, crane B). The decision threshold is '%' (ASCII 37), which sits between the two valid characters.
FUNCTION_BLOCK FB_CraneID_Detect
VAR_INPUT
CraneChar : STRING[1];
END_VAR
VAR_OUTPUT
IsCraneB : BOOL;
END_VAR
BEGIN
// If CraneChar > '%' it must be '@' (Crane B)
IsCraneB := GT_STRNG(S1 := CraneChar, S2 := '%');
END_FUNCTION_BLOCK
This pattern is robust because the two possible inputs are non-overlapping and well-separated in ASCII space. It avoids substring or numeric parsing entirely and executes in a single PLC scan-cycle with deterministic timing on an S7-1500.
Step-by-Step Troubleshooting Procedure
Use this ordered checklist when you see the GT_STRNG error cluster. Do not skip steps — early steps rule out the most common cause in seconds.
-
Verify the FC number. Open the symbol table and confirm the entry for
GT_STRNGmaps to FC15 (or the equivalent number for your CPU/firmware). Cross-check by double-clicking the call in the program editor and reading the block number in the call properties dialog. - Verify the FC is available. In TIA Portal, ensure the standard library "IEC Function Blocks" or the CPU-specific standard library is included in the project. On S7-1200 CPUs, FC15 is part of the CPU firmware; on S7-1500 it is part of the program resources.
-
Inspect the FC interface. Right-click the GT_STRNG call → "Go to definition" or "Open block". Confirm the input parameters are named
S1andS2and the return type isBOOL. Do not assume the parameter names from memory. -
Rewrite the call with the correct formal parameter names. Replace any custom names with
S1andS2exactly as declared. -
Match the function or function block return convention. For an FC, assign the result to the FC's own name (
FC100 := GT_STRNG(...)). For an FB, assign the result to aVAR_OUTPUTBOOL. - Compile and check the diagnostics window. If errors remain, read each message verbatim — TIA Portal often emits a more specific cause (e.g., "STRING length mismatch") in the second pass.
-
If errors persist: temporarily simplify the call to
GT_STRNG(S1 := 'A', S2 := 'B')with hard-coded literals. If this compiles, the issue is in how the input variables are scoped or sized.
FB vs FC: Choosing the Right Block Type
Although both an FB and an FC can host a GT_STRNG call, the choice has practical consequences for production code.
Use an FC when:
- The comparison has no internal state (no latch, edge detection, or counter).
- You want minimal memory footprint — FC temporaries live on the L stack and are released when the FC returns.
- You are calling the same comparison logic many times in one cycle with different inputs.
Use an FB when:
- You need to hold state across calls (e.g., a hysteresis flag for "crane B has been detected").
- You want to encapsulate the comparison inside a reusable block with its own multi-instance inside a parent FB.
- You need the block to appear in the call hierarchy with its own instance DB for diagnostics.
For the crane ID example, an FC is sufficient. For a "debounced" detection with rising-edge memory, an FB is required.
Common Pitfalls and Edge Cases
Pitfall 1 — Comparing STRINGs of Different Declared Lengths
STRING[1] and STRING[2] are not the same type to the compiler. Passing a STRING[2] to a VAR_INPUT declared as STRING[1] may compile with a warning or fail outright depending on TIA Portal version. Use the same declared length on both sides, or use the generic STRING (default 254) at the interface boundary.
Pitfall 2 — Comparing an Initialized-Empty STRING
Calling GT_STRNG(S1 := '', S2 := '') compiles cleanly but always returns FALSE because the actual length is zero for both operands and the comparison short-circuits. Use this only as a syntactic test, not a meaningful comparison.
Pitfall 3 — Forgetting That Strings Are Left-Justified
Assigning 'A ' (A followed by space, ASCII 65 then 32) to a STRING[2] produces the byte sequence 65 32, not 65 00. GT_STRNG compares position by position and will return FALSE if the first position matches but the second is smaller. This is rarely a problem with single-character identifiers but matters for multi-character tags.
Pitfall 4 — Mistaking GT_STRNG for I_STRNG
FC15 (GT_STRNG) and FC16 (I_STRNG) are adjacent in the standard library. Drag the FC from the correct folder: GT_STRNG is in the "String functions" or "Comparison functions" group, I_STRNG is in the "Conversion functions" group.
Verification Procedure
After applying the fix, confirm correct behaviour with these checks.
- Compile clean. The error list should show zero errors and zero warnings on the modified block.
- Download to the PLC. In TIA Portal: click "Download to device" (or press Ctrl+L) and select the target CPU. Wait for the "Download successful" confirmation.
-
Go online and monitor. Open the FB/FC instance in online mode. Force
String_Comp1 := '!'andString_Comp2 := '%'in the watch table.STRING_CRANE_VALUEshould evaluate to FALSE. -
Force the second test pair. Force
String_Comp1 := '@'andString_Comp2 := '%'.STRING_CRANE_VALUEshould evaluate to TRUE. -
Test boundary equality. Force both inputs to
'%'.STRING_CRANE_VALUEmust be FALSE (strictly greater-than, not greater-than-or-equal). -
Test empty strings. Force both to
''. Result must be FALSE; verify no scan-time watchdog error is raised. -
Capture online help text. With the cursor on the GT_STRNG call, press F1 to confirm the official Siemens help shows parameters
S1,S2, and returnBOOL.
Compiler Diagnostic Reference
Map from TIA Portal error message to root cause:
| Error Message | Likely Cause | Action |
|---|---|---|
| Invalid input, in/out, output parameter | Formal parameter name typo or wrong name used | Use S1/S2 exactly |
| Invalid Assignment | Result cannot be assigned to LHS type | Check LHS is BOOL; for FC, assign to FC name |
| Invalid or missing function type | Call cannot resolve to any FC in scope | Verify FC15 in symbol table; check library inclusion |
| Illegal parameter transfer | Type mismatch (often wrong FC number) | Confirm FC number is GT_STRNG, not I_STRNG |
| STRING length mismatch | Input STRING[n] shorter than literal passed | Increase declared length or shorten literal |
Performance and Execution Timing
On an S7-1500 CPU (firmware V2.5 and later, the GT_STRNG function executes in single-digit microseconds for STRINGs under 32 characters. For STRING[254] operands, the worst-case time is dominated by the byte-by-byte compare loop and stays below 50 µs on a typical S7-1515. There is no need to pre-compute hash codes or lengths; the standard library implementation is already optimal for PLC use.
On an S7-1200, expect 5–10× longer execution times. If the comparison runs in a fast OB (<1 ms), consider whether the call frequency is acceptable, though in practice GT_STRNG is rarely a bottleneck.
Firmware and Library Compatibility
The IEC standard string comparison functions (EQ_STRNG, NE_STRNG, GT_STRNG, GE_STRNG, LT_STRNG, LE_STRNG, I_STRNG, S_STRNG) are present in:
- All S7-1200 CPUs from firmware V1.0 onward (part of CPU firmware, not a separate library)
- All S7-1500 CPUs from firmware V1.0 onward
- All S7-300/400 CPUs with the "Standard Library → IEC Function Blocks" included
If GT_STRNG is missing from the catalog in TIA Portal, check that the project's library references include the CPU-specific standard library for your target. On older STEP 7 V5.x projects migrating to TIA Portal, the FC numbers may have shifted; always re-verify by opening the block rather than relying on legacy documentation.
Why does my GT_STRNG call produce five errors on a single line?
The five errors are cascading symptoms of one root cause. The most common is using the wrong formal parameter names — GT_STRNG expects S1 and S2, not custom names. The second most common is calling the wrong FC (FC16 I_STRNG instead of FC15 GT_STRNG). Fix either of these and all five errors will clear in a single recompile.
What is the correct function call syntax for GT_STRNG in SCL?
The correct call is Result := GT_STRNG(S1 := StringA, S2 := StringB); where Result is BOOL. Inside an FC, assign the result to the FC name; inside an FB, assign to a VAR_OUTPUT BOOL. Parameter names must be exactly S1 and S2 — they are not user-definable.
Can I compare a STRING[1] against a single character literal in SCL?
Yes. The compiler accepts GT_STRNG(S1 := SingleCharString, S2 := '%') because the literal '%' is promoted to a STRING of sufficient length. Make sure your STRING[1] input is large enough to hold the character; SCL will not silently truncate. For multi-character literals against a STRING[1] input, the comparison will reflect the actual length of the declared string.
Should I implement GT_STRNG in an FC or an FB?
Use an FC when the comparison is stateless and you want the smallest memory footprint. Use an FB when you need persistent state (edge detection, latches, counters) or when you want the call to appear in the program structure with its own instance DB for diagnostics. The syntax differs: an FC assigns the result to the FC name, an FB assigns to a VAR_OUTPUT.
How do I verify GT_STRNG is working correctly online?
Download the program, open a watch table, and force the input strings to known values. Test three cases: S1 less than S2 (expect FALSE), S1 greater than S2 (expect TRUE), and S1 equal to S2 (expect FALSE — the comparison is strictly greater-than). If all three return the expected BOOL, the function is operating correctly.