为什么 \countdef、\dimendef 等都要求自定义命名的寄存器在赋值之前为空?

为什么 \countdef、\dimendef 等都要求自定义命名的寄存器在赋值之前为空?

为什么\dA在赋值之前不能赋值\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}

答案1

语法\dimendef

\dimendef〈控制序列〉〈等于〉〈8位数〉

使用 e-TeX 扩展,该数字可以是 15 位;使用 LuaTex,该数字可以是 16 位。 的目的\dimendef是定义一个控制序列,该序列将引用可用的寄存器之一,不是设置某些维度寄存器的值。

当你说\newdimen\dA,TeX 知道最后分配的寄存器号,说n,这样就可以了

\dimendef\dA=n+ 1

(伪代码)。因此,如果最后分配的寄存器是42\newdimen\dA则将执行\dimendef\dA=43。现在,\dA将相当于\dimen43,但如果代码事先随着新的分配而发生变化,则无需知道实际数字,该数字可能会在每次运行之间发生变化。

如果你这样做\newdimen\dA,TeX 会分配一个新的寄存器编号并将其设置为 0pt (除非你篡改了寄存器,直接通过寄存器编号分配给它们)如果你这样做

\dimendef\dB\dA

所需的〈8位数〉被强制转换为寄存器的缩放点值\da,在本例中为0。事实上

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

将发行

> \dB=\dimen0.

然而,这显然是语法的误用。如果你想分配一个与 相同的值的新寄存器\dA,你去做

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

因为2.2pt是以144179比例点为单位的。但即使以比例点为单位的值在允许的范围内,\dimendef\dA=\dB新定义的寄存器之后\dA将包含以下值0pt

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

会回答

> 0.0pt.

这个故事的寓意是:绝不直接使用\dimendef,除非你想为“本地寄存器”定义名称,但是

  1. 必须集体完成;
  2. 您必须确保代码不会对与您本地使用的寄存器相同的寄存器进行分配;
  3. 你不做全球的分配给“本地寄存器”。

不遵守上述规则可能会导致奇怪的结果。

答案2

在解释数字时,例如 TeX 搜索此类寄存器编号的表达式中的寄存器编号,TeX 会将维度转换为sp并使用该sp值(不带单位)作为所指数字。因此,在您的情况下,您尝试定义\dB为不存在的寄存器编号 144179。

说明这一点的小文档,我使用\dimendef\dB\dA\dA仍然具有值时0sp,并得到\dimen0作为因此的定义\dB

\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}

在此处输入图片描述

边注:LaTeX2e 内核利用这一事实对访问第 0 个寄存器进行优化,即使用 dimen \z@,即 0sp。这样可以节省 token,因为 TeX 的内存在过去非常有限。

相关内容