> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/zh-tw/geng-duo-zhu-ti/19-how-tex-macros-actually-work-part-1.md).

# TeX 巨集實際上如何運作：第 1 部分

[第 1 部分](/latex/zh-tw/geng-duo-zhu-ti/19-how-tex-macros-actually-work-part-1.md) [第 2 部分](/latex/zh-tw/geng-duo-zhu-ti/20-how-tex-macros-actually-work-part-2.md) [第 3 部分](/latex/zh-tw/geng-duo-zhu-ti/21-how-tex-macros-actually-work-part-3.md) [第 4 部分](/latex/zh-tw/geng-duo-zhu-ti/22-how-tex-macros-actually-work-part-4.md) [第 5 部分](/latex/zh-tw/geng-duo-zhu-ti/23-how-tex-macros-actually-work-part-5.md) [第 6 部分](/latex/zh-tw/geng-duo-zhu-ti/24-how-tex-macros-actually-work-part-6.md)

## 導言：本系列的目標

本系列文章有個雄心勃勃的目標：要解釋 *如何* TeX 巨集（如 LaTeX 指令）實際上是如何運作的——在最根本的層次上，在真正的 TeX 引擎軟體內部。與其依賴 *單靠* 一套旨在展示 TeX 各種功能、邊界情況與行為的範例巨集，我們將直接檢視 TeX 本身，看看 *如何* 和 *為什麼* 它的巨集程式設計方法為何會以那樣的方式運作。

為了達成我們的目標，我們需要先討論一些相當低階的主題，而一開始這些主題看起來可能與文件排版的工作有些遙遠。希望在深入探究之後，你會建立起一個更紮實的基礎，讓你能更深入理解，最終替你省下許多時間，也或許能減少一些挫折感。

### TeX 程式語言：有同感嗎？

把 TeX 程式語言形容為有點神祕晦澀，並不算過分，因為它確實如此——至少以現今大多數主流程式語言的標準來看是這樣。當你開始踏上學習 TeX/LaTeX 的旅程時，特別是如果你想撰寫不只是簡單片段的巨集，你很快就會遇到像是類別碼、標記／標記化，以及指令或巨集的「展開」等概念。這一連串概念很可能相當陌生，或許會讓你感到困惑，有時甚至略感挫折，因為你通往成功的道路並不總是有 TeX/LaTeX 那些幾乎難以理解的錯誤訊息相助。

## 那麼，我們從哪裡開始？從類別碼開始。

TeX 引擎屬於一類稱為 [編譯器](https://en.wikipedia.org/wiki/Compiler)：會讀入以某種 *來源* 語言撰寫的檔案，並且 *編譯* （轉換）成一個以某種 *目標* 語言撰寫的輸出檔。更具體地說，TeX 是一種 *文件編譯器*。對 TeX 引擎（編譯器）而言，輸入檔以 TeX 排版語言撰寫，而目標則是另一種「語言」所寫的輸出檔，例如 [DVI](https://en.wikipedia.org/wiki/Device_independent_file_format) 或 PDF——雖然我們對「語言」的概念有點寬鬆。

讓我們更仔細看看撰寫 TeX 檔案所使用的來源，或輸入，「語言」。一個 `.tex` 檔案最終只是一長串字元（包含換行字元）：其中夾雜著將被排版的文字，以及 `\\`, `}`, `$`, `[` 和各式各樣、能以看似近乎無限的組合方式出現的字元。任何不使用 TeX/LaTeX 的人看到一個典型的 `.tex` 檔案時，大概會覺得那是一團相當混亂的字元，幾乎看不出有任何可見的檔案結構。LaTeX 巨集套件確實在某種程度上對 .tex 輸入檔「施加」了一些基本結構。然而，在 `\begin{document}` 和 `\end{document}` 那裡該放些什麼，則由文件作者自行決定。如果你看看 `.tex` 以 Knuth 原始的 Plain TeX 巨集套件所撰寫的檔案，你會發現文件結構幾乎完全不存在。

因此，一般來說，TeX 輸入檔看起來可能相當沒有結構，似乎只是將要排版的內容與指示該內容排版方式的指令混雜在一起。TeX 究竟怎麼可能理解一個典型的 `.tex` 輸入檔：要如何把那團湧入的字元混合物過濾成對排版引擎可執行的指令，以及應該被排版的內容？

### 過濾雜亂訊息：向類別碼問好

任何對 TeX 一無所知的人類觀察者，看到一個 `.tex` 檔案時，可能會辨認出某些字元，例如 `$` 並知道那是貨幣符號，或看到一個 `&` 並將其辨識為與號。該觀察者會為每個看到的字元推斷出一種 *意義* 意義——這種意義基於該字元在人類溝通中所扮演的角色。此外，他們可能會看到像 `a`, `e`, `或` 這樣的字元，並知道它們被歸類為母音，而其他像 `b`, `c` 或 `d` 則被歸類為子音。作為人類，我們的記憶中彷彿內建了一個查找表，透過它我們為所見的每個字元指定意義——根據該字元在我們所能溝通的語言中所扮演的角色來賦予意義。

要處理一個 `.tex` 檔案，TeX 軟體也必須查看輸入中的每個字元，並且同樣需要為每一個它「看見」的字元指定一個 *意義* 給它所「看見」的每一個字元。然而，TeX 只是一台以軟體實作的機器，負責處理文字——這些文字以整數序列（字元碼）的形式儲存在輸入檔中。作為一台機器，TeX 必須預先編程好相關資料，告訴它如何判定它所「看著」的字元之意義，並進一步決定接下來要如何處理它。TeX 是如何做到這一點的呢？

答案就是那種只有 TeX 才有的概念之一： *類別碼，* 共有 16 種，範圍從 0 到 15。就 TeX 而言，它預期在一個 `.tex` 檔案中看到的每個字元，都有所謂的 *類別碼* 預先指定給它的類別碼。在 TeX 軟體內部有一種「查找表」，列出 *目前* 分配給 TeX 可能在輸入 .tex 檔中看到的每個字元。你可以把 TeX 的類別碼想成是為 *意義* TeX 必須檢查（掃描）的輸入串流中的每個個別字元指定一個

要將文件排版，TeX 引擎必須讀入（掃描）每一個字元，但 TeX 當下關注的並不是實際字元（字元碼）：字元的 *類別碼* 在掃描輸入時更為重要。字元的 *目前* 類別碼決定了 *目前意義* 的意義 *在 TeX 讀入它的當下*：該類別碼決定 TeX 將如何對每個字元加以對待／處理——我們稍後會說明為什麼要說「目前類別碼」和「目前意義」。TeX 正是透過類別碼來過濾湧入的字元混合物，區分出那些注定要排版的字元（內容）與那些構成待處理指令的字元——*命令* 也就是 TeX 需要執行的。

下表列出這 16 種類別碼：它們各自代表什麼，以及通常被指派到各類別的字元範例。

| **類別碼** | **說明**                           | **標準 LaTeX/TeX**             |
| ------- | -------------------------------- | ---------------------------- |
| 0       | 逸脫字元——告訴 TeX 開始尋找命令              | `\\`                         |
| 1       | 開始一個群組                           | {                            |
| 2       | 結束一個群組                           | }                            |
| 3       | 數學切換——切換進入／離開數學模式                | $                            |
| 4       | 對齊定位符                            | &                            |
| 5       | 行尾                               | ASCII 編碼 13（`\r`)            |
| 6       | 巨集參數                             | #                            |
| 7       | 上標——用於排版數學： `$y=x^2$` $$y=x^2$$  | ˆ                            |
| 8       | 下標——用於排版數學： `$y=x_2$` $$y=x\_2$$ | \_                           |
| 9       | 被忽略的字元                           | ASCII 0 `<空值>`               |
| 10      | 間隔字元                             | ASCII 編碼 32（空格）和 9（Tab 鍵字元）  |
| 11      | 字母                               | A...Z、a...z，以及數千個 Unicode 字元 |
| 12      | 其他                               | 0...9 加上 ,.;?" 以及許多其他字元      |
| 13      | 活動字元                             | 用於建立單字元巨集的特殊類別代碼，例如 ˜        |
| 14      | 註解字元——忽略後面直到行尾的所有內容              | %                            |
| 15      | 無效字元，不允許出現在 .tex 輸入檔中            | ASCII 編碼 127（`刪除`)           |

類別碼的使用是 TeX 用來過濾其輸入字元流的核心機制，讓它能理解你的輸入並判定：

* 構成將被排版之文字的字元；
* 用來界定應以數學排版的內容；
* 作為待處理或執行之指令名稱的字元序列；
* ……以及許多其他排版操作。

一開始，你可能會以為每個字元的類別碼（意義）是一種固定配置：不可改變，並且永久內建在 TeX 軟體的核心基礎中，但事實並非如此。如前所述，TeX 內部維護著一張查找表，用來儲存哪個類別碼被 *目前* 指派給每個字元——我們特別刻意使用 *目前指派* ，因為任何字元（尚未讀入）的類別碼都可以透過一個名為 `\catcode`的原始（內建）指令來變更。這帶來相當大的彈性，因為如果你願意，你可以徹底改變 TeX 之後從輸入讀入的任何字元的處理或解讀方式，為複雜的排版應用提供極大的可能性。

如果你主要關心的是用 LaTeX「把事情做完」，你很可能並未直接遇過類別碼，除了也許從你看過的錯誤訊息中見過它們。不過請放心，類別碼是 TeX 引擎運作的核心組件：它們使 LaTeX（以及 LaTeX 套件）能真正完成將文件排版的工作。

當你的 TeX 引擎啟動時（「[啟動](https://en.wikipedia.org/wiki/Bootstrapping)」）它會使用一組預設的字元到類別碼配置，但透過 `\catcode` 指令，這些預設值可由核心 LaTeX 程式碼（巨集）和／或你已載入的 LaTeX 套件加以變更——或者也可以由你自己的 TeX 程式碼或巨集來改變。不過，隨著時間與傳統／慣例的累積，某些被指派到特定類別碼的字元已被公認為「標準」，若你希望文件具備可攜性並能輕鬆與同事或其他使用者分享，遵循這些標準當然是理想的。例如， `\\` 字元被分配到類別碼 0，以表示 TeX/LaTeX 指令的開頭——請參見 [上表](#tbl-0).

### 讀取（掃描）輸入

當 TeX 從你的輸入檔讀取（掃描）下一個字元時，它首先會查看其類別碼，因此讓我們更仔細看看 TeX 讀取一行典型輸入時會發生什麼事。

假設我們有一個 .tex 檔，其中包含文字 `Hello World \jobname` 在某段段落中的某處。如果我們打開 `.tex` 檔案，使用 [十六進位編輯器](https://en.wikipedia.org/wiki/Hex_editor)，我們會看到字元序列 `Hello World \jobname` 在我們的 `.tex` 檔案中只是一串整數，或 *字元碼*，如下方截圖所示的十六進位序列：

`48, 65, 6C, 6C, 6F, 20, 57, 6F, 72, 6C, 64, 20, 5C, 6A, 6F, 62, 6E, 61, 6D, 65, 20`

![TeX 檔中的十六進位字元碼](/files/1becd05cc81305e50d9c622064687e49cdbe8839)

如果我們將其從十六進位（基數 16）轉換為十進位（基數 10），字元碼序列如下：

![TeX 檔中的十進位字元碼](/files/4b8d5294bd6c3bd6d297cff8cad909b6ed4ab794)

我們也知道，對 TeX 而言，每個字元都有對應的類別碼；因此，根據 [上表](#tbl-0) 這一點，我們知道下列預設的類別碼配置（大概）也正在使用：

![TeX 類別碼](/files/2158c7e698ebb093dc0a7a5512560bc34823e2ca)

因此，對 TeX 而言，輸入檔中的每個字元都由 *兩個* 兩個數值所表示——其字元碼和其類別碼：

![字元碼及對應的 TeX 類別碼](/files/aaf27223e170d1846766de7a45b6ae26c917d5a6)

到這一點為止，我們只是在考慮 TeX 處理你的檔案的第一個階段：掃描個別字元。那麼，TeX 究竟會如何處理這些成對的字元碼與類別碼？一旦 TeX 掃描了某個字元並查找出其對應的類別碼，它究竟如何利用這些資訊來「過濾」湧入的字元？

## 第 2 部分

在第 2 部分，我們將更仔細地看看 TeX 如何讀取你的輸入：假裝成 TeX 的「眼睛」，逐字元地觀察你的輸入。

[第 1 部分](/latex/zh-tw/geng-duo-zhu-ti/19-how-tex-macros-actually-work-part-1.md) [第 2 部分](/latex/zh-tw/geng-duo-zhu-ti/20-how-tex-macros-actually-work-part-2.md) [第 3 部分](/latex/zh-tw/geng-duo-zhu-ti/21-how-tex-macros-actually-work-part-3.md) [第 4 部分](/latex/zh-tw/geng-duo-zhu-ti/22-how-tex-macros-actually-work-part-4.md) [第 5 部分](/latex/zh-tw/geng-duo-zhu-ti/23-how-tex-macros-actually-work-part-5.md) [第 6 部分](/latex/zh-tw/geng-duo-zhu-ti/24-how-tex-macros-actually-work-part-6.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/zh-tw/geng-duo-zhu-ti/19-how-tex-macros-actually-work-part-1.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
