为什么 ANSI 只指定外部标识符中最小的有效字符数为六个?(涉及 IT 技术)

17
我有一个问题,涉及第一份《美国国家标准编程语言-C》(也称ANSI/ISO 9899-1990、ISO/IEC 9899.1990 (E)、C89等)中第5.2.4.1节“翻译限制”。简单来说,这是第一个ANSI C标准。该标准说了什么令人感到奇怪?它声名狼藉地指出,符合C标准的编译器只需要处理以下内容:“5.2.4.1翻译限制:外部标识符中的前6个显着字符”。显然,这太短了,特别是考虑到C没有类似名称空间的东西。当处理外部标识符时,允许使用描述性名称尤为重要,因为它们会“污染”链接的所有内容。
即使是标准库中的函数名也很长,例如longjmptmpfilestrncat。其中后者strncat表明他们必须努力发明库名称,使前六个字符唯一,而不是更合理的strcatn,因为它将与strcat发生冲突。

为什么这对我仍然是个问题?

我喜欢旧式计算机。我正在尝试编写程序,以便在C99之前的平台上编译并且能够正常工作,但有时在我心爱的目标上不存在这种情况。也许我还喜欢真正遵循标准。通过挖掘旧标准,尝试追踪某些限制和实现问题的原因,我已经学到了很多关于C99和C11的知识。

因此,即使我不知道任何编译器或链接器实际上会强制执行或施加此限制,如果我还想使用易读且不冲突的外部标识符,那么我仍然无法声称编写了严格符合标准的代码,这令我感到困扰。

为什么他们会施加这样的限制呢?

他们在80年代早期开始标准化工作,并在1988或1989年完成。即使在70年代和60年代,处理更长的标识符也不会有任何问题。
考虑到任何想要符合新标准的编译器都必须进行修改 - 即使仅是更新文档 - 我不认为ANSI坚定地说出类似于“现在已经是1989年了。您必须处理31个重要的初始字符”这样的话是不合理的。对于任何平台,甚至是古老的平台,这都不会成为问题。
向后兼容性?
从我搜索到的内容来看,问题可能来自FORTRAN。在对C(变量中的“重要字符”的确切角色是什么?的回答中,Jonathan Leffler写道:
“问题的一部分可能是Fortran;它只需要支持6个字符的单音节名称,因此在广泛使用Fortran的系统上链接器不需要支持更长的名称。”对我来说,这似乎是回答“为什么?”最合理的答案。但考虑到每当我想编写一个理论上可以在旧系统上构建的程序时,这种限制都会让我感到困扰,我想知道更多细节。”

问题

  1. 在搜索了一些关于FORTRAN轨迹的资料后,我只找到了理论和手舞足蹈的东西。哪些流行平台确实限制了只能使用6个字符?有没有一种特别流行的链接器,迫使标准委员会让步?
  2. 当这些细节被讨论时,我还不够老,对此并不感兴趣。这个限制及其原理是否公开讨论和辩护过?是否有公众强烈反应,或者只是默默无闻?有人在ANSI总部外举起了长柄耙子吗?

最终,这些问题的答案将使我更容易决定给我的函数取一个合理的名称,以便我晚上睡得更好。


1
好问题。我也有同样的疑问,感谢你在这里发帖! - behkod
2个回答

14

30年前,大多数世界上的代码都是用Cobol、Fortran和PL/1编写的,其中绝大部分运行在IBM 370系列大型计算机或兼容机上。全世界大部分的C语言代码都是在DEC的PDP-11和VAX小型计算机上运行的。Unix和C语言诞生于PDP上,DEC硬件是它们的主要平台。

正是这个时代孕育了ANSI C委员会,并在这个时代里他们考虑了如何将C语言编写的代码与其他真正重要的编程语言以及真正重要的操作系统相互链接。

当时的Fortran编译器只支持Fortran 77,并将标识符限制为6个字符。而PL/1编译器则将外部标识符的长度限制为7个字符。S/370系统链接器将符号截断为8个字符。巧合的是,PDP-11汇编语言要求符号在前6个字符内唯一。

ANSI C委员会规定外部标识符必须有6个初始有效字符,委员会并没有因此而遭受指责。这意味着可以在IBM大型计算机上实现符合规范的编译器;不仅如此,这个编译器无需太过担心PDP-11汇编器的限制,并且可以生成与Fortan 77可以链接的代码。这个规定完全没有任何轰动效应。就像ANSI C委员会无法管制苏联导弹设计一样,他们也无法强制改变IBM大型计算机链接器的规定。

已经是1989年了。你必须处理31个初始有效字符。即使是古老的平台,这也不是问题。

你对此并不正确。请将摩尔定律向后倒推30年,并尝试想象当时委员会工作时计算机有多么微小。当时支持数百个用户以及运行大型公司所有数据处理系统的大型计算机通常仅具备比我旧版的谷歌Nexus平板电脑稍高一点的处理能力、内存和存储资源。

1985年的IBM 3380E硬盘单元容量为5.0GB,售价约12万美元;按今天的货币计算大约27万美元。其传输速率为24Mbps,约为我的笔记本电脑硬盘的2%。在这样的参数下,系统需要存储、读取或写入每一个字节,每一次硬盘旋转,每个时钟周期都会对底线产生影响。而且,这一直是事实,只不过更加明显。以字节为粒度的吝啬式存储经济已经深植于编程实践之中,而那些简短的公共符号名称只是其中一种表达方式。

当然,问题并不在于那些占据了1980年代文化和决策的微弱但价格惊人的大型机和小型机不能够支持语言、编译器、链接器和编程实践,其中这种吝啬的存储经济(以及其他一切)被抛弃。当然,如果每个人都有一个像笔记本电脑或手机一样的设备,它们肯定可以。但是,如果没有它,它们就无法支持购买来运行的巨大多用户工作负载。软件需要极度精简才能完成如此多的任务。


1
非常感谢您提供这个精彩的答案!我确实没有考虑到多用户主机,尽管我仍然不确定这是否是一个好理由。无论编译哪种代码,外部声明的存储空间都会淹没在其他需要存储的内容中 - 无论是在内存中还是在磁盘上。然而,我可以理解这可能在当时被视为一个原因。 - pipe
1
MsDos / Windows使用8个字符的名称(+ 3个字符类型)。很长一段时间,更长的文件名被实现为Fudge(8个字符的名称是唯一的)。从记忆中可以得知,Windows XP(2002年??)是第一个完全支持长文件名的版本。在此之前,所有系统程序都必须少于8个字符。 - Bruce Martin
1
有没有难度指定一种语法来定义内部和外部名称不同的函数(例如,可以声明double integrate(double p[]) extern "int"来表示该函数应在C中使用名称“integrate”进行定义,但导入或导出的符号应称为“int”[否则在C中无法使用此名称]?)一些特定的实现具有这样的功能,但是否存在标准语法的困难? - supercat
1
"字节粒度" 可能应该改为 "位粒度" -- 我曾处理过在字节边界上编码子8位值的消息协议! - M.M
2
有趣的是,那台1989年的老电脑实际上可以为那100个用户提供服务,而现在的设备对于1个用户来说常常都太多了。 - peterh
显示剩余8条评论

0

在BTL,最初我写了“n”函数,如strcpyn等,大约是在1977年...当时忘记了,在IBM S/370上使用IBM OS(MVS、VM/CMS)的C语言中,限制externs为7个字符,因此其他人将其更改为strncpy等,因为我们正在努力使C语言在许多遗留系统中实现可移植性,包括IBM和Univac 11xx。 到1980年,限制已经提高到8个字符,但strn已经在使用中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接