重温Borland Turbo C/C++:90年代伟大的IDE






4.96/5 (28投票s)
回顾 Borland Turbo C/C++
我必须承认,我当年并不是Turbo C的重度用户。我作为程序员的旅程始于Turbo Pascal,然后是QBASIC,接着是Microsoft Visual Basic 3.0。虽然我当时在我的Tandy 1000上与Turbo Pascal一起安装了Turbo C 3.01,但直到多年以后,我才开始大量使用Turbo C,作为工作中嵌入式系统项目的一部分。
最近,我有一些空闲时间,从winworldpc下载了Turbo C和Turbo C++,并在NTVDMx64上进行了尝试。一个“Hello World
”程序在Turbo C 1.0上运行良好,就像在现代编译器上一样。
显然,人们可以指出早期IDE的许多局限性。没有语法高亮,也无法设置断点。在线帮助是可用的,但仅限于IDE使用,不涵盖C语言语法。
“Edit”菜单似乎很烦人,因为它似乎什么都不做(没有子菜单等),除了将光标设置到编辑窗口。这个无用的菜单保留在Turbo C 2.0和Turbo Pascal 5.5中,直到Turbo C 3.0和Turbo Pascal 6才被一个支持Cut/Copy/Paste的完整菜单取代。尽管有这个无用的“Edit”菜单,编辑器还是支持块选择、查找和替换等功能,使用Wordstar快捷键,例如Ctrl-Q-F进行查找,CTRL-Q-A进行替换。这些快捷键中的大部分都在在线帮助中有所描述。
是的,在线帮助指的是随软件套装(例如软盘)一起提供的帮助文本,而不是许多人认为的来自互联网。当时,由于存储容量有限,大多数软件都附带印刷手册,在线帮助被认为是一项了不起的成就。Visual Studio 2008也有“在线”帮助(通过MSDN Library CD安装),并且包含(除其他外)丰富的C语言文档——你只需将光标放在一个C函数上然后按F1。在更新版本的Visual Studio中,语言帮助可以通过将浏览器指向相关的MSDN页面来提供。
由于IDE文件日期为1987年7月6日,而ANSI-C直到1989年(称为C-89)才最终定稿,因此现代C编译器中习以为常的许多功能都不可用。例如,单行注释,如
// this is a comment
将不会被接受,并会产生“表达式语法”错误。显然,像二进制表示法(0b10101010)这样的更现代的功能也不被接受——你必须使用十六进制表示法,例如0xAA。即使是Visual Studio 2008也不支持此功能,因为二进制表示法是C++ 14的一部分,并且仅从Visual Studio 2015或更高版本开始支持。我想知道现代软件开发者如今有多少东西是理所当然的。
在Turbo C 1.0中,声明函数参数类型是可选的,默认假定为int。以下代码将成功编译并正常工作
void test(a, b)
{
a = 4;
b = 5;
printf("%d %d\n", a, b);
}
void main()
{
test(4,5);
}
以下代码仍然可以编译,但由于堆栈不平衡将导致未定义行为(最有可能挂起或崩溃),因为Turbo C编译器未能检测到所需的参数未提供。
void test(a, b)
{
a = 4;
b = 5;
printf("%d %d\n", a, b);
}
void main()
{
test();
}
以下代码将导致编译错误(参数过少)——如果声明了参数类型,Turbo C会正确检测到缺失的参数。
在Turbo C 2.0中,Borland增加了对断点和C语言在线帮助的支持。将光标放在一个单词上,然后按Ctrl-F1获取相关帮助。在线帮助仍然不包含代码示例(这些直到Turbo C 3.0才添加)。IDE的颜色主题现在是黄底蓝字。
显然,你不能在注释或不会产生代码的行(例如,没有初始化器的声明)上设置断点。如果你在Visual Studio这样的现代IDE中这样做,断点将自动移到下一条可接受的行。如果你在Turbo C中这样做,下次运行代码时会显示一条消息(无效断点,忽略,擦除,清除所有无效,跳过所有无效)。
我办公室里一位计算机科学博士曾试图在Visual Studio中做同样的事情,并抱怨IDE有bug。别跟我提这个。
Turbo C 2.0还支持使用Borland Graphics Interface (BGI)进行图形处理。你可以通过运行BGIDEMO.C来获取支持功能的演示。
如果代码无法编译,请检查Options > Directories,并确保路径设置正确(例如,include目录的路径为C:\TC\INCLUDE)。还要检查Options > Linker,并启用图形库的链接。Turbo C安装程序会在安装时设置这些值,但如果你后来移动了TC目录,则必须手动更改这些路径。
与这些早期IDE一样,代码可以在不保存文件到磁盘的情况下进行编译和运行!你必须每次都按F2,否则如果需要重新启动计算机,数据将会丢失。我相信此功能是为了避免过多的软盘写入。对于Turbo Pascal来说,此行为也同样适用。然而,Turbo Pascal的克隆Free Pascal会在第一次编译前提示用户保存文件,并在后续编译过程中自动保存。
在Turbo C/C++ 3.0中,添加了语法高亮和代码示例。
在Options > Preferences中还增加了一个选项,可以为EGA显示43行,为VGA显示50行。
我很少在实体PC上使用此功能,因为字符高度会缩小(以容纳更多行),导致文本难以阅读。
然而,在模拟器上,这可能很有用,因为窗口高度现在被扩展了,可以显示更多行,但字符高度却没有降低。这是一张50行模式下帮助窗口的截图,该窗口描述了“auto”关键字,这可能是C语言中最无用的关键字。
根据上述帮助文本,局部变量的局部生存期是默认的,因此auto关键字很少使用。如果是这样,你什么时候需要使用这个关键字?我将这个问题留给读者练习。
Turbo C 3.0还支持鼠标、窗口编辑、调试监视和项目,这些功能在我们现在使用的现代IDE中都非常熟悉。要转到函数声明,请使用Search > Locate function,这仅在你成功编译代码后才有效。除了自动完成功能对复杂项目很有用之外,该IDE被认为是相当成熟的。
Free Pascal IDE试图实现自动完成功能,但它相当有限,并且只适用于某些关键字(procedure、begin、end、repeat等),而对函数参数不起作用。可用的关键字列表可以在Options > Environment > CodeComplete中配置。
Turbo C 2.0是最后一个可以在8088上运行的版本。更高版本需要保护模式(例如,至少需要80286),但编译后的可执行文件可以在8088上运行(具有正确的链接器设置)。库CONIO.H和DOS.H包含许多有用的函数,如clrscr()
、gotoxy()
、sound()
和delay()
,它们在现代机器上也能很好地工作,并且不会像Turbo Pascal的CRT单元那样出现运行时错误200。我之前曾使用Turbo C为PC XT开发过一个MIDI播放器,详情请参见这篇文章。
各种游戏,如Commander Keen in Keen Dreams,也是使用Turbo C开发的。我曾研究过这款游戏的源代码,并意识到它有几个宏来启用或禁用Disney Sound Source的支持。例如,在id_sd.c文件中,大约在第1494行,你可以看到原始的检测例程(包括Sound Blaster和Disney Sound Source)已被禁用,只留下Adlib和PC speaker的支持。
#if 0 // DEBUG - hack for Keen Dreams because of no space...
// Use the best sound hardware available
if (SoundBlasterPresent)
sd = sdm_SoundBlaster;
else if (SoundSourcePresent)
sd = sdm_SoundSource;
else if (AdLibPresent)
sd = sdm_AdLib;
else
sd = sdm_PC;
#else
if (AdLibPresent)
sd = sdm_AdLib;
else
sd = sdm_PC;
#endif
然而,一旦启用,只会听到随机的声音,因为原本为Disney Sound Source设备播放的实际音频样本从未准备好,这解释了为什么这些代码被注释掉了。如果启用了Sound Blaster检测,音频不会有任何变化。Sound Blaster向后兼容Adlib,游戏只是播放Adlib声音,因为除了自动检测之外,没有专门支持Sound Blaster。你可以通过从上面的Github存储库下载代码,并使用Project > Open Project打开KDREAMS.PRJ项目文件来亲自尝试。
如果你像我一样,使用Turbo C与并行端口进行接口,请注意,要使用的正确函数是DOS.H中的inportb
和outportb
(而不是inb
/outb
)。与Turbo Pascal不同,没有PORT
/PORTW
数组,也没有Mem
/MemW
/MemL
数组来提供对实模式内存(例如MEM[segment:offset]
)的直接访问。要做到这一点,你需要将地址文字转换为指针,并通过该指针访问端口。
char* pointer = (char*)0x1173000; // calculate using segment*16 + offset
char value = *pointer;
char first_byte = pointer[0];
char second_byte = pointer[1];
总而言之,Turbo C至今仍然是一个非常有用的IDE。我相信它仍被一些印度学校用来教学生C语言的基础知识。它没有自动完成等功能,但这些功能并非真正必需,并且可能会削弱早期学习的努力。不,我完全反对那些老派教授,他们要求学生在纸上写数百行代码来参加期末考试,但如果你想成为一名优秀C开发者,记住printf()
或strcpy()
的基本语法肯定是必要的。无论如何,如果你不能用Turbo C写一个(比如说)显示前100个素数的程序,那么Visual Studio 2022也帮不了你。对我而言,Turbo C目前正在一台旧机器上运行,用于开发一款现代化的老式硬件模拟器,而且该IDE至今未令我失望。