Variable Types

Variable Number Type of Variable NOTE
#0 Null
#1#33 Local Variables Reset to null when program ends
#100#199 Common Variables
#500#999 Global Variables Keep value when machine is turned off
#1000 and up System Variables

Variable Declaration

All Fanuc macro variables begin with # followed by a number. The number identifies which variable you are reading or writing.

#100 = 25.4       (ASSIGN 25.4 TO COMMON VARIABLE 100)
#1 = 0            (ASSIGN ZERO TO LOCAL VARIABLE 1)
#500 = #5021      (COPY CURRENT X POSITION INTO PERMANENT VARIABLE 500)
#[#100] = 3.0     (INDIRECT: ASSIGN 3.0 TO THE VARIABLE WHOSE NUMBER IS IN #100)

Values are stored as floating-point numbers with up to 8 significant digits of precision. Variables can hold numbers with or without decimal points.

If you write #100=1 without a decimal, it is stored as the integer 1. If you write #100=1.0, it is stored as floating-point 1.0. Both behave the same in arithmetic, but best practice is to always include the decimal point for clarity—especially in G-code where the presence or absence of a decimal can change the meaning of an address word.

Null vs Zero

This is the single most important concept in Fanuc macro programming. A variable can be null (vacant, empty, undefined) or it can hold the value zero. These are not the same thing, and confusing them is the #1 source of macro bugs.

Behavior Null (#0 / vacant) Zero (0 / 0.0)
In arithmetic Null result propagates through the expression Normal zero behavior (add, subtract, multiply, etc.)
#n EQ 0 FALSE TRUE
#n EQ #0 TRUE FALSE
#n NE 0 TRUE FALSE
On CNC display Shows blank or asterisks (********) Shows 0.000
As axis word X#n Address X is omitted entirely from the block Moves to X0.0
Clearing to null #n = #0 N/A

A variable that has never been assigned is null, not zero. The expression #100 = #0 explicitly sets #100 to null (clears it). This distinction matters enormously for probing macros and conditional logic—for example, an optional axis argument that is null will cause the axis word to be skipped, but if it is zero the machine will move to zero.

Local Variables (#1 – #33)

Local variables are used as argument receivers when a macro is called with G65. Each letter in the G65 call maps to a specific local variable number (A→#1, B→#2, C→#3, and so on).

Property Detail
Range #1#33
Scope Private to each macro call level (nesting creates a new set)
Lifetime Reset to null when the macro call level returns (M99)
Nesting G65 nesting creates up to 4 levels of local variable scope
Sharing Not shared between programs—each G65 call gets its own copy

When a macro is called via G65, any argument letters in the call are mapped to specific local variable numbers. Arguments not specified in the call remain null. This is why the null vs zero distinction matters: you can check whether an argument was passed by testing if the variable is null.

G65 P9100 A1.0 B2.0 Z-10.0
(INSIDE O9100:)
(  #1 = 1.0   ... A argument)
(  #2 = 2.0   ... B argument)
(  #26 = -10.0 ... Z argument)
(  #3 = #0    ... C was not passed, so #3 is null)

For the complete letter-to-variable mapping, see Argument Variables.

Common Variables (#100 – #199)

Common variables are shared across all programs and macro levels. Any program can read or write them at any time, regardless of call depth.

Property Detail
Range #100#199
Scope Global—shared across all programs and macro levels
Persistence Volatile—cleared (set to null) on power cycle, reset, or M02/M30 (depending on parameter settings)
Count 100 variables available

Typical uses: passing data between programs, temporary calculation storage, loop counters, intermediate results.

Warning: since these variables are shared, two macros that run in sequence (or that call each other) can interfere if they use the same variable numbers. Document which variables each macro uses, or establish a shop convention for variable allocation.

Permanent Common Variables (#500 – #999)

Permanent common variables have the same shared scope as #100–#199, but their values are retained through power off. Data survives power cycles, resets, and program end.

Property Detail
Range #500#999
Scope Global—shared across all programs and macro levels
Persistence Non-volatile—retained through power off, reset, and program end
Count 500 variables available

Typical uses: tool wear tracking, part counters, calibration values, probe results, custom fixture offsets, and any data that must survive between power cycles.

Warning: do not use these for temporary data—they accumulate stale values that can cause subtle bugs days or weeks later. Always clear permanent variables when they are no longer needed.

Many shops establish reserved ranges to avoid collisions between macros. For example:

Range Convention (example)
#500#549 Probing results & calibration
#550#599 Tool management
#600#699 Part counters & production tracking
#700#999 General-purpose / custom macros

System Variables (#1000+)

System variables provide read-only or read/write access to the CNC control's internal state. They are organized in numbered ranges, where each range corresponds to a different category of machine data.

Range Purpose
#1000#1199 PMC interface (machine I/O signals)
#2001#2800 Tool offset data
#3000#3006 Alarms, operator messages, clock
#4001#4120 Modal G-code state
#5001#5086 Position data (machine, workpiece, skip signal)
#5201#5400 Work coordinate offsets (G54–G59)
#7001#7944 Extended work offsets (G54.1 P1–P48)
#10001#13999 Tool geometry and wear offsets (extended format)

Some system variables are read-only (e.g., position data), while others can be written to change machine state (e.g., work offsets, tool offsets). Writing to the wrong system variable can cause unexpected machine behavior—always consult the Fanuc Parameter Manual before writing to unfamiliar system variables.

For the complete list, see Fanuc System Variables.

Indirect Variable Access

Indirect variable access uses the syntax #[expression], where the result of the expression is used as the variable number. This is one of the most powerful features in Fanuc macro programming.

#100 = 500         (STORE VARIABLE NUMBER 500 IN #100)
#[#100] = 25.4     (EQUIVALENT TO: #500 = 25.4)
#101 = #[#100]     (EQUIVALENT TO: #101 = #500 ... READS 25.4)

If #100 = 500, then #[#100] is equivalent to #500. The expression inside the brackets is evaluated first, and the result becomes the variable number.

Array-Like Iteration

Indirect access is essential for iterating through a range of variables, creating array-like behavior that Fanuc Macro B does not otherwise support.

#100 = 500                        (START AT VARIABLE 500)
WHILE [#100 LE 510] DO1
IF [#[#100] NE #0] THEN #3000=1 (FOUND NON-NULL VALUE)
#100 = #100 + 1                 (NEXT VARIABLE)
END1

This loop checks variables #500 through #510 for any non-null value. Without indirect access, you would need to write 11 separate IF statements.

Double Indirection

You can nest indirection: #[#[#100]] reads the variable whose number is stored in the variable whose number is in #100. For example, if #100 = 501 and #501 = 600, then #[#[#100]] resolves as follows:

(GIVEN: #100 = 501, #501 = 600, #600 = 3.14159)
#102 = #[#[#100]]
(STEP 1: INNER #[#100] = #[501] = #501 = 600)
(STEP 2: OUTER #[600] = #600 = 3.14159)
(RESULT: #102 = 3.14159)

Double indirection is rare in practice but useful for lookup tables and pointer-based data structures in advanced macros.

See Also

See also: Argument Variables for G65 letter-to-variable mapping, Fanuc System Variables for the complete #1000+ reference, and Macro Control Flow for null-variable gotchas in conditionals.

References

  • Peter Smid, Fanuc CNC Custom Macros, Industrial Press, 2004.
  • Fanuc, Operator’s Manual / Parameter Manual, FANUC Corporation.

Have a question or want to contribute?

Contact us with corrections, additions, or topics you'd like covered.

Get in Touch