C99不支持函数重载有什么原因吗?

9nvpjoqh  于 2023-01-25  发布在  其他
关注(0)|答案(3)|浏览(142)

显然(至少根据gcc -std=c99)C99不支持函数重载。不支持C中的一些新特性的原因通常是向后兼容性,但在这种情况下,我想不出函数重载会破坏向后兼容性的任何情况。不包括这个基本特性背后的原因是什么?

gcuhipw9

gcuhipw91#

要理解为什么在C中不太可能看到重载,更好地了解C++是如何处理重载的可能会有所帮助。
在编译代码之后,但在它准备运行之前,中间的 * 目标代码 * 必须被链接。这将编译函数和其他对象的粗略数据库转换为准备加载/运行的二进制文件。这个额外的步骤很重要,因为它是编译程序可用的模块化的主要机制。这个步骤允许您从现有库中获取代码,并将其与您自己的应用程序逻辑混合。
在这一阶段,目标代码可能是用任何语言编写的,具有任何特性组合。为了实现这一点,必须有某种约定,以便链接器能够在另一个对象引用它时选择正确的对象。如果你用汇编语言编写代码,当你定义一个标签时,该标签会被准确地使用,因为它假定你知道你在做什么。
在C中,函数成为链接器的符号名,所以当你写

int main(int argc, char **argv) { return 1; }

编译器提供目标代码档案,该档案包含称为X1 M0 N1 X的对象。
这很好用,但是这意味着你不能有两个同名的对象,因为链接器不能决定它应该使用哪个名字。链接器对参数类型一无所知,对代码也知之甚少。
C通过将附加信息直接编码到符号名中来解决这个问题。返回类型、参数的数量和类型、参数的引用类型、参数是否为const等都被添加到符号名中,并在函数调用时以这种方式引用。链接器甚至不必知道这一点正在发生,因为就其所知,函数调用是明确的。
这样做的缺点是符号名看起来和原始函数名一点也不像。特别是,几乎不可能预测重载函数的名称,以便链接到它。要链接到外国代码,可以使用extern "C",这会使这些函数遵循C风格的符号名,但当然你不能重载这样的函数。
这些差异与每种语言的设计目标有关。C语言面向可移植性和互操作性。C语言致力于做可预测和兼容的事情。C
更强烈地面向构建丰富和强大的系统,而不是特别关注与其他语言的交互。
我认为C不太可能追求任何会产生像C++那样难以交互的代码的特性。

编辑Imagist询问:

如果将int main(int argc,charargv)解析为main-int-int-char而不是main(这是标准的一部分),是否真的会降低可移植性或更难与函数交互?我看不出这有什么问题。事实上,在我看来,这给了您更多的信息(可以用于优化等)
为了回答这个问题,我将再次转向C和它处理重载的方式。C使用这个机制,几乎和描述的完全一样,但有一个警告。C没有标准化它自己的某些部分应该如何实现,然后继续建议这种省略的一些后果。特别是,C有一个丰富的类型系统,它包括虚类成员。如何实现这个特性留给了编译器编写者,并且vtable解析的细节对函数签名有很大的影响。因此,C特意建议编译器编写者使名称修饰在编译器之间或在同一编译器中使用这些关键特性的不同实现时相互不兼容。
这只是更深层次问题的一个症状,即虽然像C
和C这样的高级语言有详细的类型系统,低级机器代码是完全无类型的。2任意丰富的类型系统建立在机器级提供的无类型二进制代码之上。3链接器不能访问高级语言可用的丰富类型信息。链接器完全依赖于编译器来处理所有类型抽象并生成正确的无类型目标代码。
C通过在被破坏的对象名称中编码所有必要的类型信息来实现这一点。然而,C有一个明显不同的焦点,它的目标是成为一种可移植的汇编语言。因此,C更喜欢在声明的名称和结果对象的符号名称之间有一个严格的一一对应关系。如果C破坏了它的名称,即使是以一种标准化和可预测的方式,你将不得不花很大的力气把修改后的名字和想要的符号名匹配起来,否则你将不得不像在c中那样把它关掉。2这种额外的努力几乎没有任何好处,因为不像C++,C的类型系统相当小而且简单。

与此同时,定义几个名称相似的C函数,只是它们作为参数的类型不同,这实际上是一种标准做法。

p1tboqfb

p1tboqfb2#

当你编译一个C源代码时,符号名将保持不变。如果你引入了函数重载,你应该提供一个名称修饰技术来防止名称冲突。因此,像C++一样,你将在编译的二进制文件中拥有机器生成的符号名。
另外,C语言没有严格的类型。在C语言中,很多东西可以隐式地相互转换。重载解析规则的复杂性可能会在这种语言中引入混乱。

whhtz7ly

whhtz7ly3#

包括我在内的许多语言设计者都认为,函数重载与C语言的隐式提升相结合会导致代码极其难以理解。要想找到证据,请查看有关C++的大量知识积累。
一般来说,C99是一个温和的修订,大致上与现行做法一致,而超载则是一个相当大的偏离。

相关问题