I'm aware that some "temporary" LaTeX dimensions etc. exist. I would, however, like to know all of them.
I know \reserved@a
(macro), \@tempdima
(dimension) and \@tempcnta
(counter).
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It only takes a minute to sign up.
Sign up to join this communityThe use of scratch registers and macros in TeX/LaTeX date back to the time when it was absolutely essential to conserve memory consumption, because TeX's memory (both in terms of token/macro memory as well as number of available registers) was very limited and one could easily run out of space just by loading a few packages on top of the main format.
Traces of this can be still found all over the place in the code, e.g., you see things like \@plus
as an abbreviation for the 5 tokens plus
so that each time this was needed in code you would save 4 tokens. The same is true for registers which were limited to a total number of 256 of each type and loading, say pictex
could already get you close to the total limits in available count and dimen registers.
However, using scratch registers and macros to overcome these limitations always came with a price: there is always the danger that the register or macro got reused while your code is still assuming that it holds your value! And despite a lot of precautions (like using them only within a group or ensure that setting and use would be really really next to each other) time and time again it caused bugs and issues because macros got called within arguments of others (both assuming that they could safely use the same scratch object) or through the fact that the output routine is visited in unexpected situations changing the context.
With LaTeX2e which was born 1994 or so the size limitation got even worse because the core code got extended. So we had to use scratch registers all over the place and conserve memory as best as we could. But knowing the issues with them we split the scratch registers into two: those that we wanted to see only being used within kernel code and those that had been used in the past by third party packages already (and which we couldn't take away without breaking those package). Therefore we introduced \reserved@...
hoping that the name clearly indicates that they are not intended for use by package authors.
Bottom line: use of scratch registers and macros is not advisable unless there is a very good reason and these days the original reason (the memory limitation) is no longer valid. All modern TeX installations (younger than a decade or so) these days are based on eTeX and all offer enough space and registers that it is much better and simpler if packages use their own private commands and registers and therefore can rely on living side by side without any headache.
With LaTeX3 (expl3
) we recommend not to use any scratch registers at all even though we do offer a few as we know that old habits do not die easily.
expl3
is that they are useful for quick 'in document' stuff (truly localised to one use case), but should not be used in anything produced as a package or class.
The LaTeX kernel allocates some scratch registers and defines a scratch conditional. The complete list is
\newcount\@tempcnta
\newcount\@tempcntb
\newif\if@tempswa
\newdimen\@tempdima
\newdimen\@tempdimb
\newdimen\@tempdimc
\newbox\@tempboxa
\newskip\@tempskipa
\newskip\@tempskipb
\newtoks\@temptokena
Notice that for the first two \newcount
is used, rather than \newcounter
. All these registers and \if@tempswa
(with the companion macros \@tempswatrue
and \@tempswafalse
) must be used only locally, so never assigned values with the \global
prefix.
The register allocation mechanism always leaves free the first ten register numbers, so also
\dimen0 ... \dimen9
\skip0 ... \skip9
\toks0 ... \toks9
and box registers 0 to 9 are free for scratch usage. An agreed upon convention (that unfortunately some packages don't follow) is that even numbered scratch registers should be used locally, and odd numbered ones should be used globally. Also for local usage are
\count@
\dimen255
\skip255
\toks255
but not box register 255; \count@
is an alias for \count255
, actually, while \dimen@
, \skip@
and \toks@
stand for the 0 register of each type.
The kernel uses also \reserved@a
, \reserved@b
, \reserved@c
, \reserved@d
and \reserved@e
as scratch macros, but apart from special tasks, it's better not using them in packages or personal macros. The macro \@gtempa
is used as "global scratch macro" and its meaning should always be set globally.
Also registers \muskip0
to \muskip9
are available as scratch registers, but I don't know of any packages that uses them.
Usage of scratch conditional and registers should follow some simple rules.
Never rely on their value before using them, therefore initialize their value at the start of the job.
Avoid calling macros that might use the same scratch registers during the time you need those register to have a relied upon value, unless the call is made inside a group, so that the previous value will be restored at group end.
In case of doubt, don't use scratch registers, but allocate your own.
Any register can be used as scratch register, provided this is done inside a group and following the rules above (but with more care about possible value clobbering). So it's fairly common to find \count0
and \count2
used as scratch registers inside a group; this is safe, provided nothing that can trigger a page break is performed. Why? The value of the counters \count0
to \count9
is recorded in the DVI or PDF output during a \shipout
operation (if nonzero, for the registers numbered 1 to 9); the LaTeX counter page
is actually \count0
.
A very common pitfall is in the usage of box registers which do follow the group structure, with the peculiarity that \box
and \unhbox
destroy the current incarnation of the box register. So, after
\setbox0=\hbox{foo}\begingroup\box0\endgroup
the box register 0 will be void. On the other hand,
\setbox0=\hbox{foo}\begingroup\setbox0=\hbox{bar}\box0\endgroup
will result in box register 0 still containing \hbox{foo}
.
This might only be a partial answer, depending on your view of other packages that might also define scratch registers/variables.
Searching latex.ltx
you'll find a number of temporary things (actually defined in ltalloc.dtx
):
\newcount\@tempcnta
\newcount\@tempcntb
\newdimen\@tempdima
\newdimen\@tempdimb
\newdimen\@tempdimc
\newbox\@tempboxa
\newskip\@tempskipa
\newskip\@tempskipb
\newtoks\@temptokena
There's also \newif\if@tempswa
, but this falls under the same umbrella as \@reserved@...
, as commented by Joseph.
\toks@
(\toks0
): not all of the scratch items have sensible names :-)
\label
s and using it for other things could influence the behaviour?
\skip@
, \dimen@
, \dimen@i
and \dimen@ii
? Would these also be considered temporary?
\if@tempswa
and when the conditional is used, it's always initialized at the start. When using a "scratch" register (or boolean) one should ensure that this usage will not clobber the same registers. In case of doubt a new register or conditional must be allocated.
\reserved@...
set are not really 'temporary' in the same sense as\@tempa
or\@tempdima
: thereserved
is there for a reason (team use only)!