@tempdima,reserved@a,@tempcnta,还有什么?

@tempdima,reserved@a,@tempcnta,还有什么?

我知道存在一些“临时”的 LaTeX 尺寸等。但是,我希望了解所有这些尺寸。

我知道\reserved@a(宏观)、\@tempdima(维度)和\@tempcnta(反面)。

答案1

TeX/LaTeX 中临时寄存器和宏的使用可以追溯到节省内存消耗绝对必要的时代,因为 TeX 的内存(包括标记/宏内存以及可用寄存器的数量)非常有限,并且仅在主格式上加载几个包就很容易耗尽空间。

这种痕迹在代码中随处可见,例如,您会看到像\@plus这样的内容是 5 个标记的缩写plus,因此每次在代码中需要它时,您都会节省 4 个标记。对于寄存器也是如此,每个类型的总数限制为 256 个,并且加载,例如pictex已经可以接近可用计数和维度寄存器的总限制。

但是,使用临时寄存器和宏来克服这些限制总是要付出代价的:总是存在寄存器或宏被重用的危险,而您的代码仍然假设它保存着您的值!尽管采取了很多预防措施(例如仅在组中使用它们,或确保设置和使用确实彼此相邻),但它一次又一次地导致了错误和问题,因为宏在其他参数中被调用(两者都假设它们可以安全地使用相同的临时对象)或者由于在意外情况下访问输出例程会改变上下文。

随着 1994 年左右诞生的 La​​TeX2e 的大小限制变得更加严重,因为核心代码得到了扩展。所以我们不得不在各处使用临时寄存器,并尽可能节省内存。但我们知道这些问题,所以我们将临时寄存器分成两部分:一部分是我们希望只在内核代码中使用的,另一部分是过去已经被第三方软件包使用过的(如果不破坏这些软件包,我们就无法删除它们)。因此,我们引入了临时寄存器,\reserved@...希望名称清楚地表明它们是不是旨在供软件包作者使用。

底线:使用临时寄存器和宏是不是除非有非常好的理由,并且如今原始原因(内存限制)不再有效,否则不建议这样做。如今所有现代 TeX 安装(不到十年左右)都是基于 eTeX 的,并且都提供了足够的空间和寄存器,因此如果软件包使用自己的私有命令和寄存器,则可以更方便、更简单,因此可以放心地并行使用而不会出现任何问题。

使用 LaTeX3 ( expl3) 我们建议根本不使用任何临时寄存器尽管我们确实提供了一些,但我们知道旧习惯不会轻易消失。

答案2

LaTeX 内核分配了一些暂存寄存器并定义了暂存条件。完整列表如下

\newcount\@tempcnta
\newcount\@tempcntb
\newif\if@tempswa
\newdimen\@tempdima
\newdimen\@tempdimb
\newdimen\@tempdimc
\newbox\@tempboxa
\newskip\@tempskipa
\newskip\@tempskipb
\newtoks\@temptokena

请注意,前两个\newcount使用的是,而不是\newcounter。所有这些寄存器和\if@tempswa(以及伴随宏\@tempswatrue\@tempswafalse)必须仅在本地使用,因此绝不用前缀分配值\global

寄存器分配机制总是留下前十个寄存器号,因此

\dimen0 ... \dimen9
\skip0 ... \skip9
\toks0 ... \toks9

并且盒子寄存器 0 到 9 可自由用于暂存。一个公认的惯例(不幸的是,有些软件包不遵循)是偶数暂存寄存器应在本地使用,奇数暂存寄存器应在全局使用。对于本地使用,还有

\count@
\dimen255
\skip255
\toks255

不是box寄存器255;\count@是的别名\count255,实际上,而\dimen@\skip@\toks@代表每种类型的0寄存器。

内核也使用\reserved@a、、和作为临时\reserved@b宏,但除了特殊任务外,它最好\reserved@c\reserved@d\reserved@e不是在包或个人宏中使用它们。该宏\@gtempa用作“全局临时宏”,其含义应始终全局设置。

寄存器也\muskip0可以\muskip9用作临时寄存器,但我不知道有任何软件包使用它们。

临时条件和寄存器的使用应该遵循一些简单的规则。

  1. 在使用它们之前永远不要依赖它们的值,因此在作业开始时初始化它们的值。

  2. 当您需要这些寄存器具有可依赖的值时,请避免调用可能使用相同临时寄存器的宏,除非在组内进行调用,以便在组末恢复先前的值。

  3. 如有疑问,使用临时寄存器,但分配您自己的寄存器。

任何寄存器可以用作临时寄存器,前提是这是在组内完成的,并且遵循上述规则(但要更加注意可能的值破坏)。因此,在组内找到\count0并用作临时寄存器是相当常见的;这是安全的,前提是没有执行任何可以触发分页的操作。为什么?计数器的\count2值在操作期间记录在 DVI 或 PDF 输出中(如果非零,则为编号为 1 到 9 的寄存器);LaTeX 计数器实际上是。\count0\count9\shipoutpage\count0


一个非常常见的陷阱是使用盒子寄存器时遵循组结构,其特点是\box\unhbox破坏框寄存器的当前化身。因此,之后

\setbox0=\hbox{foo}\begingroup\box0\endgroup

框寄存器 0 将无效。另一方面,

\setbox0=\hbox{foo}\begingroup\setbox0=\hbox{bar}\box0\endgroup

将导致盒子寄存器 0 仍然包含\hbox{foo}

答案3

这可能只是部分答案,取决于您对可能也定义临时寄存器/变量的其他包的看法。

搜索latex.ltx你会发现一些临时的东西(实际上定义在ltalloc.dtx):

\newcount\@tempcnta
\newcount\@tempcntb
\newdimen\@tempdima
\newdimen\@tempdimb
\newdimen\@tempdimc
\newbox\@tempboxa
\newskip\@tempskipa
\newskip\@tempskipb
\newtoks\@temptokena

还有,但正如约瑟夫所评论的,\newif\if@tempswa这与属于同一范畴。\@reserved@...

相关内容