---
outline: deep
---

# 字符与布尔值

> 计算机中的字符并非我们平常所指的单个文字。特定的编码方案首先需要将单个文字对应到若干个码位，存储码位时还需要转换为字节序列。
>
> 布尔值往往通过二进制的 0 和 1 来表示。

## 字符

我们通常简单地将“字符”解释为我们能够看到、操作的单个文字，例如 `Z`、`天`、`👍`。

但在计算机中则不同：与整数、实数的表示一样，要表示字符，就需要首先划定能够表示的字符范围，为这个范围内的字符分配唯一的数字。在 Unicode 中，这个唯一的数字被称为“码位”（Code Point）。

尽管大多数情况下，码位与字符一一对应，但实际仍然存在很多特殊情况。

比如 `à` 和 `à` 看上去是同一个字符、编辑时删起来也感觉是单个字符，但其实前者只占一个码位（U+00E0），而后者则是普通拉丁字母 `a`（U+0061）与组合用重音符 `◌̀`（U+0300）的序列，占两个码位。日常生活中常见的 emoji 也有很多需要多个码位才能够表示。

因此，现代编程语言中常常会避免可能存在歧义的“字符”，转而使用“码位”或特定编码的“编码单元”作为最基础的单位来描述字符串相关的概念。

### Unicode 码位字面量

zig 中并没有专门的字符类型，与之最接近的是 Unicode 码位字面量。

使用单引号将文字包围，就是 Unicode 码位字面量。这是一种 `comptime_int` 类型的值，表示的是单个 Unicode 码位。

<<<@/code/release/char-and-boolean.zig#char

### 字符串字面量

zig 中的字符串字面量是一个[单项指针](../advanced_type/pointer#单项指针)，指向的是将字符串进行 UTF-8 编码后得到的字节数组。这个数组和 C 语言中的字符串一样，都是[以 NUL 字符结尾](../advanced_type/array#哨兵数组)的。因此，字符串字面量既可以隐式转换为 `u8` 切片，也可以隐式转换为以 0 结尾的指针。

<<<@/code/release/char-and-boolean.zig#string-literal

与 C 语言不同的是，zig 中的字符串字面量与 Unicode 码位字面量并没有任何的关系。对字符串字面量求索引得到的是编码序列中的某个字节，并不是 Unicode 码位。但由于 UTF-8 编码兼容 ASCII，所以对于 ASCII 字符而言，两者的数值恰巧相等。

正确处理 UTF-8 字符串是一件相当复杂的工作。标准库在 [`std.unicode`](https://ziglang.org/documentation/master/std/#std.unicode) 包中提供了用来操作 Unicode 码位和 UTF-8 编码序列的工具。

:::tip 🅿️ 只能是 UTF-8 编码吗？

其实并不是。字符串字面量可以借助 `\xNN` 转义序列存放任意形式的数据。

但 zig 源文件使用 UTF-8 编码，并且 `\u{NNNNNN}` 转义序列固定生成的是码位对应的 UTF-8 编码序列，所以字符串字面量在正常情况下存放的都是 UTF-8 数据。

:::

多行字符串字面量使用 `\\` 开头，不会执行任何转义，不包含最后一行的换行。

<<<@/code/release/char-and-boolean.zig#multiline-string-literal

### C 中的字符类型

zig 还提供了 `c_char` 类型，对应 C 中的 `char` 类型。主要用于与 C 的交互，其他情况下不建议使用。

:::details `u8` 和 `c_char`

`u8` 和 `c_char` 并不是全等的，因为 `c_char` 虽然是 8 位，但是它是否有符号取决于 target (目标机器)。

:::

## 布尔值

> 常用于流程控制

在 zig 中，布尔值有两个，分别是 `true` 和 `false`， 它们在内存中占用的大小为1个字节。
