What's the difference between \hfil and \hskip0cm plus 1fil?

\hfil inserts a glue that is exactly equivalent (identical) to that inserted by \hskip 0pt plus 1fil. The only difference is that:

  • \hfil is a primitive, so it doesn't have to scan the input text for a glue specification,
  • in other words, \hskip 0pt plus 1fil does involve scanning the input for a glue spec, which can result in funny differences depending on what comes after the 1fil.

See the clever examples in David Carlisle's answer, or even just \hfil minus forty versus \hskip 0pt plus 1fil minus forty.


Why does \hfil exist as a primitive? As TeX is one of the most-documented programs in existence, we can actually look this up. If you invoke texdoc errorlog (or read it online), you'll see this entry for 23 July 1979:

from errorlog

The “E” means it's a change made for “Efficiency”.

In the old (pre-TeXbook, and for TeX78) TeX manual, the one published in 1979 as part of “TeX and METAFONT: New Directions in Typesetting”, in Appendix X: Recent Extensions to TeX (page 201 of the “TeX” part of the book), it says:

The new control sequences \hfil, \hfilneg, \hss are short for \hskip 0pt plus 100000pt, \hskip 0pt plus -100000pt, \hskip plus 100000pt minus 100000pt, respectively, and they take less TeX memory space. The vertical analogs are \vfil, \vfilneg, and \vss.

(At that time the fil/fill/filll units and orders of “infinity” didn't exist; those came later: see the entry for 7 Aug 1981 in errorlog.)


And to confirm that \hfil really does the same thing, we can look at the TeX program source code (around the section 1058 mentioned above) (texdoc tex or read online):

1058 1060

(Unfortunately the above is hard to understand unless you are familiar with the special conventions of the TeX program, but the main point is that \hskip and \hfil invoke the same internal function (procedure) append_glue, except that in the \hfil case the glue specification is a hard-coded fil_glue, and in the \hskip case it is scanned using scan_glue.)


\hfil and \hskip0cm plus 1fil make identical glue items so tests such as your box example will be identical in the same way that \hskip0cm plus 1fil is the same as \hskip 0 pt plus 1fil, However they differ as tokens and the way they are scanned.

Notably of course, after

\def\zzA{\hfil}

and

\def\zzB{\hskip0cm plus 1fil}

Then

\zzA look and \zzB look

show different behaviour, and similarly after

\def\gobble#1{}


\expandafter\gobble\zzA  and \expandafter\gobble\ZZB