extern
This commit is contained in:
parent
d1d1c88934
commit
95871ff6bf
8 changed files with 117 additions and 118 deletions
47
README.md
47
README.md
|
@ -49,14 +49,14 @@ $ sh boot.sh
|
|||
|
||||
自举会输出六个文件,三个汇编文件和三个可执行文件:
|
||||
|
||||
| 源代码 | 编译器 | 汇编 | 可执行 | 代号 | 命名 |
|
||||
| ----------------- | --------- | ------- | --------- | ---- | ---------------------- |
|
||||
| boot.c boot-lib.c | gcc | | gcc.out | G | 自制编译器 |
|
||||
| boot.c boot-lib.h | gcc.out | boot1.s | boot1.out | B1 | 自举自制编译器 |
|
||||
| boot.c boot-lib.h | boot1.out | boot2.s | boot2.out | B2 | 自举自举自制编译器 |
|
||||
| boot.c boot-lib.h | boot2.out | boot3.s | | B3 | 验证自举自举自制编译器 |
|
||||
| 源代码 | 编译器 | 汇编 | 可执行 | 代号 | 命名 |
|
||||
| ------ | --------- | ------- | --------- | ---- | ---------------------- |
|
||||
| boot.c | gcc | | gcc.out | G | 自制编译器 |
|
||||
| boot.c | gcc.out | boot1.s | boot1.out | B1 | 自举自制编译器 |
|
||||
| boot.c | boot1.out | boot2.s | boot2.out | B2 | 自举自举自制编译器 |
|
||||
| boot.c | boot2.out | boot3.s | | B3 | 验证自举自举自制编译器 |
|
||||
|
||||
后三次编译时,boot-lib.h 的内容被手动导入 boot.c 开头进行编译,boot-lib.c 提供的库通过链接引入。
|
||||
除了第一次编译全程由 gcc 完成之外,另外三次编译从源码到汇编由本编译器完成,从汇编到可执行文件由 gcc 完成。从汇编到可执行文件时需要将 glibc 链接进去,这对于 gcc 来说是默认的行为。
|
||||
|
||||
整个自举及其验证的过程如下图所示:
|
||||
|
||||
|
@ -95,7 +95,7 @@ $ sh boot.sh
|
|||
|
||||
### 关键字
|
||||
|
||||
本语言包含的关键字即为支持的标量类型的关键字和流程控制的关键字,还有 `const`。
|
||||
本语言包含的关键字即为支持的标量类型的关键字和流程控制的关键字,还有 `const` 和 `extern`。
|
||||
|
||||
#### `const` 关键字
|
||||
|
||||
|
@ -103,15 +103,29 @@ $ sh boot.sh
|
|||
|
||||
但是当在出现
|
||||
|
||||
- 全局,标量(即不是数组)
|
||||
- 类型为 `const int` 或 `const int const`
|
||||
- 带有初始化
|
||||
- 全局,标量(即不是数组)。
|
||||
- 类型为 `const int` 或 `const int const`。
|
||||
- 带有初始化。
|
||||
- 不是 `extern` 的。
|
||||
|
||||
的声明时,将会被解析为整数常量。
|
||||
|
||||
整数常量在使用的时候会被直接替换为对应的右值,失去作为全局变量左值的性质。
|
||||
|
||||
使用 `int const` 或 `int` 可以避免这样的特殊处理。
|
||||
使用 `int const` 或 `int` 形式或添加 `extern` 可以避免这样的特殊处理。
|
||||
|
||||
#### `extern` 关键字
|
||||
|
||||
`extern` 在全局函数和变量的声明的开头中可以使用。
|
||||
|
||||
全局函数的声明和定义都会直接忽略这个关键字。全局函数的声明和定义由是否提供函数体决定,与该关键字无关。
|
||||
|
||||
全局变量如果使用了这个关键字,则有以下特性和限制:
|
||||
|
||||
- 变量仅被声明,而没有被定义。
|
||||
- 如果需要使用这样的变量,需要稍后提供定义,或在外部已经定义。
|
||||
- 不可以初始化。
|
||||
- 不可是数组。
|
||||
|
||||
### 支持以下运算符
|
||||
|
||||
|
@ -144,7 +158,6 @@ $ sh boot.sh
|
|||
|
||||
- 支持全局变量和局部变量,局部变量遮挡全局变量。
|
||||
- 不支持局部变量之间的遮挡,重名的局部变量为同一变量。
|
||||
- 支持函数声明,可以通过函数声明来调用 C 语言库。不支持变量声明。
|
||||
- 函数只支持最多八个参数。函数声明中支持可变参数,仅用于兼容 C 语言库。
|
||||
- 类型检查有遗漏,若 C 编译器报错,而本语言编译通过,就可以认为是 UB。
|
||||
- 例如函数调用的参数和 `return` 语句不会检查类型。
|
||||
|
@ -165,14 +178,12 @@ $ sh boot.sh
|
|||
|
||||
## 依赖
|
||||
|
||||
直接依赖下面这些 C 语言库函数,在本语言中提供声明后调用。
|
||||
直接依赖下面这些 C 语言库函数和变量,在本语言中提供声明后调用。
|
||||
|
||||
- `printf`
|
||||
- `getchar`
|
||||
- `exit`
|
||||
|
||||
间接依赖下面这些 C 语言库函数,在 C 语言中进行封装后调用。
|
||||
|
||||
- `ungetc`(理论上非必须,可以在本语言中手动模拟)
|
||||
- `vfprintf` 和可变参数有关的宏(用于输出调试信息,非必须)
|
||||
- `ungetc` 和 `stdin`(理论上非必须,可以在本语言中手动模拟)
|
||||
- `fprintf` 和 `stderr`(理论上非必须,仅用于输出错误信息)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue