# Chapter 002: Compilation Error
# Status: Timeline 1972.11.3
# Location: Bell Labs, Building 2
>>> Timeline Jump Complete
>>> Current Location: Bell Labs, 1972
>>> Mission: Fix critical compilation error in C compiler
>>> Warning: This bug could affect all future C programs
>>> Status: Initializing local environment...
世界重新聚焦时,我发现自己坐在一张堆满纸张的办公桌前。桌上放着一台更新的终端机,型号是PDP-11/45。
"嘿,你能帮我看看这个编译器的问题吗?"
我转过头,看到Dennis Ritchie正在翻看一叠打印纸。这次我来到了C语言诞生的关键时刻。
$ ls
cc.c
cgen.c
cgram.y
clex.c
sym.h
...
这是最早期的C编译器源代码。据历史记载,在C语言发布前,有一个严重的编译错误差点导致整个项目延期。
我调出了编译器的源代码:
typedef struct {
int t_op;
int t_type;
int t_value;
struct node *t_left;
struct node *t_right;
} node;
void compile(node *tree) {
if (tree == NULL) return;
switch(tree->t_op) {
case PLUS:
compile(tree->t_left);
compile(tree->t_right);
emit("ADD");
break;
case ASSIGN:
if (tree->t_left->t_type != tree->t_right->t_type) {
// 类型检查有问题
implicit_cast(tree->t_right, tree->t_left->t_type);
}
compile(tree->t_right);
store(tree->t_left);
break;
// ...
}
}
"看到问题了吗?"Ritchie问道,"有些程序编译时会产生错误的代码,特别是涉及类型转换的时候。"
我仔细检查着代码。这是早期C语言最关键的部分之一:类型系统。如果这里出现问题,将影响到未来几十年的程序开发。
突然,我注意到了问题所在:
void implicit_cast(node *expr, int target_type) {
if (expr->t_type == INT && target_type == FLOAT) {
emit("ITOF");
} else if (expr->t_type == FLOAT && target_type == INT) {
emit("FTOI");
} else if (expr->t_type == CHAR && target_type == INT) {
// 这里漏掉了符号扩展
emit("LOAD1"); // 只加载一个字节
}
expr->t_type = target_type;
}
"找到了,"我说,"类型转换的实现有问题。"
这个bug如果不修复,将导致所有从char到int的转换都忽略符号位,使得负数变成大的正数。这在后来会造成无数的程序错误。
我开始修改代码:
void implicit_cast(node *expr, int target_type) {
if (expr->t_type == INT && target_type == FLOAT) {
emit("ITOF");
} else if (expr->t_type == FLOAT && target_type == INT) {
emit("FTOI");
} else if (expr->t_type == CHAR && target_type == INT) {
emit("LOADS"); // 带符号扩展的加载
emit("EXTEND"); // 扩展到完整的int
}
expr->t_type = target_type;
}
"我们来测试一下,"我说着,写下了一个测试程序:
char c = -1;
int i = c;
printf("%d\n", i);
$ cc test.c
$ ./a.out
-1
"完美!"Ritchie看着输出结果说,"现在类型转换正确保留了符号位。"
我们继续测试了更多的情况:
void test_conversions() {
char c1 = -128;
char c2 = 127;
int i1 = c1; // 应该是 -128
int i2 = c2; // 应该是 127
float f = i1; // 浮点数转换
// ...
}
所有的测试都通过了。这个修复不仅解决了当前的问题,还为C语言后来成为系统编程的标准语言奠定了基础。
"对了,"Ritchie突然说,"我们还在考虑是否要添加'unsigned'类型..."
我的心跳漏了一拍。unsigned类型!这是C语言另一个重要的特性。但在我能回答之前,熟悉的眩晕感又来了。
>>> Mission Completed
>>> Timeline Stable
>>> Bug Fixed: Sign Extension in Type Conversion
>>> Historical Impact: Moderate
>>> Note: C Language Type System Stabilized
>>> Preparing for next jump...
世界再次开始模糊。在消失前,我看到Ritchie在笔记本上写下了什么。也许这就是unsigned类型诞生的时刻。
每一个bug的修复都在改变着历史,而程序员们却从未知晓。这让我想起了一句古老的谚语:站在巨人的肩膀上。只是在这里,我是在帮助巨人站得更稳。
# End of Chapter 002
# Next Timeline Loading...
梦远书城已将原网页转码以便移动设备浏览
本站仅提供资源搜索服务,不存放任何实质内容。如有侵权内容请联系搜狗,源资源删除后本站的链接将自动失效。
推荐阅读