# Why \countdef, \dimendef, and alike require custom-named register to be empty before assignment?

Why \dA can't be assigned a value before it is assigned to \dB?

\documentclass[varwidth,border=5mm]{standalone}
\begin{document}
\newdimen\dA
\dimendef\dB\dA % ERROR IF PRECEDED BY NEXT LINE
\dA=2.2pt % CANNOT PRECEDE PREVIOUS LINE
\the\dB % SOME RANDOM VALUE (NOT 2.2pt)
\end{document}

• Because \dA doesn't act as the registers number in this case, but as the value saved in register \dA in sp, so you're trying to create a new dimen in register 144179. – Skillmon Nov 18 at 8:23

The syntax for \dimendef is

\dimendef〈control sequence〉〈equals〉〈8-bit number〉

With e-TeX extensions the number can be 15-bit; with LuaTex it can be 16-bit. The purpose of \dimendef is to define a control sequence that will refer to one of the available registers, not to set the value of some dimension register.

When you say \newdimen\dA, TeX knows the last allocated register number, say n, and it will do

\dimendef\dA=n + 1

(in pseudocode). So, if the last allocated register is 42, \newdimen\dA will do \dimendef\dA=43. Now, \dA will be equivalent to \dimen43, but one doesn't need to know the actual number, which might change from one run to another, if the code changes with a new allocation beforehand.

If you do \newdimen\dA, TeX allocates a new register number and sets it to 0pt (unless you have tampered with registers assigning to them directly by register number). If you do

\dimendef\dB\dA


the required 〈8-bit number〉 is coerced to be the value in scaled points of the register \da, in this case 0. Indeed

\newdimen\dA
\dimendef\dB\dA
\show\dB


will issue

> \dB=\dimen0.


However, this is clearly a misuse of the syntax. If you want to allocate a new register with the same value as \dA, you have to do

\newdimen\dA
\dA=2.2pt
\newdimen\dB
\dB=\dA


because 2.2pt is 144179 in scaled points. But even if the value in scaled points was in the allowed range, after \dimendef\dA=\dB the newly defined register named \dA would contain the value 0pt:

\dA=2sp
\dimendef\dA\dB
\showthe\dA


> 0.0pt.


The moral of the story is: never use \dimendef directly, unless you want to define names for “local register”, but

1. this must be done in a group;
2. you have to make sure that the code doesn't do assignments to registers that may be the same as those you use locally;
3. you don't do global assignments to the “local registers”.

Failure to comply with the above rules can lead to weird results.

• @Skillmon That's clear, but… – egreg Nov 18 at 11:25

When interpreting numbers, such as the register number in expressions where TeX searches for such register numbers, TeX converts dimensions to sp and uses that sp value (without the unit) as the meant number. So in your case you're trying to define \dB to register number 144179, which doesn't exist.

Little document that illustrates this, I use \dimendef\dB\dA when \dA has still the value 0sp, and get \dimen0 as the definition for \dB therefore:

\documentclass[preview,border=3.14]{standalone}

\begin{document}
\newdimen\dA
\texttt{\meaning\dA}

\dimendef\dB\dA
\texttt{\meaning\dB}

\dA=2.2pt
\number\dA
\end{document}


Side note: The LaTeX2e kernel uses this fact as an optimization when accessing the 0th registers, by using the dimen \z@, which is 0sp. This way it can save on tokens, since TeX's memory was quite limited back in the days.