第3章 第002章_编译错误

# 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...

梦远书城已将原网页转码以便移动设备浏览

本站仅提供资源搜索服务,不存放任何实质内容。如有侵权内容请联系搜狗,源资源删除后本站的链接将自动失效。

推荐阅读

仓鼠后备军

小欢喜:成长系统

今日有囍

我靠线人系统在刑侦文里当热心市民

我的恋爱指数要满仓

< 上一章 目录 下一章 >
×
量子纠缠:我,林深,在代码里修改世界线
连载中无黯001 /