C99不支持函数重载是有原因的吗? [英] Is there a reason that C99 doesn't support function overloading?

查看:102
本文介绍了C99不支持函数重载是有原因的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

显然(至少根据 gcc -std = c99 而言),C99不支持函数重载。不支持C中某些新功能的原因通常是向后兼容,但在这种情况下,我无法想到一种情况,函数重载会破坏向后兼容性。不包含此基本功能的原因是什么?

Apparently (at least according to gcc -std=c99) C99 doesn't support function overloading. The reason for not supporting some new feature in C is usually backward compatibility, but in this case I can't think of a single case in which function overloading would break backward compatibility. What is the reasoning behind not including this basic feature?

推荐答案

要了解为什么您不太可能看到C重载,它可能有助于更好地了解C ++如何处理重载。

To understand why you aren't likely to see overloading in C, it might help to better learn how overloading is handled by C++.

在编译代码之后,但在准备运行之前,必须链接中间的目标代码。这会将编译后的函数和其他对象的粗略数据库转换为可以加载/运行的二进制文件。此额外步骤很重要,因为它是可用于已编译程序的模块化原理机制。此步骤使您可以从现有库中获取代码,并将其与您自己的应用程序逻辑混合。

After compiling code, but before it is ready to run, the intermediate object code must be linked. This transforms a rough database of compiled functions and other objects into a ready to load/run binary file. This extra step is important because it is the principle mechanism of modularity available to compiled programs. This step allows you to take code from existing libraries and mix it with your own application logic.

在此阶段,目标代码可能是用任何语言编写的,功能的任意组合。为了使之成为可能,必须有某种约定,以便链接器可以在其他对象引用正确的对象时选择该对象。如果您使用汇编语言进行编码,则在定义标签时,该标签将被完全使用,因为假定您知道自己在做什么。

At this stage, the object code may have been written in any language, with any combination of features. To make this possible, it's necessary to have some sort of convention so that the linker is able to pick the right object when another object refers to it. If you're coding in assembly language, when you define a label, that label is used exactly, because it is assumed you know what you're doing.

在C中,函数成为链接器的符号名称,因此在您编写时

In C, functions become the symbol names for the linker, so when you write

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

编译器提供了目标代码的存档,其中包含名为的对象main

the compiler provides an archive of object code, which contains an object called main.

这很好,但这意味着您不能有两个名称相同的对象,因为链接器将无法确定应该使用哪个名称。链接器对参数类型一无所知,而对代码的了解却很少。

This works well, but it means that you cannot have two objects with the same name, because the linker would be unable to decide which name it should use. The linker doesn't know anything about argument types, and very little about code in general.

C ++通过直接将其他信息编码到符号名称中来解决此问题。返回类型以及参数的数量和类型将添加到符号名称中,并在函数调用时以这种方式进行引用。链接器甚至不必知道这种情况正在发生,因为就其所知,函数调用是明确的。

C++ resolves this by encoding additional information into the symbol name directly. The return type and the number and type of arguments are added to the symbol name, and are referred to that way at the point of a function call. The linker doesn't have to know this is even happening, since as far as it can tell, the function call is unambiguous.

此方法的缺点是符号名称看起来不像原始函数名称。特别是,几乎不可能预测重载函数的名称,以便您可以链接到它。要链接到前码,可以使用 extern C ,这会使这些函数遵循符号名称的C样式,但是您当然不能重载该函数。

The downside of this is that the symbol names don't look anything like the original function names. In particular, it's almost impossible to predict what the name of an overloaded function will be so that you can link to it. To link to foriegn code, you can use extern "C", which causes those functions to follow the C style of symbol names, but of course you cannot overload such a function.

这些差异与每种语言的设计目标有关。 C面向可移植性和互操作性。 C竭尽全力去做可预测和兼容的事情。 C ++更着重于构建功能强大的系统,而不是非常注重与其他语言的交互。

These differences are related to the design goals of each language. C is oriented toward portability and interoperability. C goes out of its way to do predictable and compatible things. C++ is more strongly oriented toward building rich and powerful systems, and not terribly focused on interacting with other languages.

我认为C不太可能追求任何会产生与C ++一样难以交互的代码的功能。

I think it is unlikely for C to ever pursue any feature that would produce code that is as difficult to interact with as C++.

编辑 Imagist 问:


如果您解析int main(int
argc,char ** argv)改为
main-int-int-char **而不是main
(这是标准的一部分)?
我在这里没看到问题。实际上,
在我看来这为您提供了
更多的信息(可以将
用于优化等)

Would it really be less portable or more difficult to interact with a function if you resolved int main(int argc, char** argv) to something like main-int-int-char** instead of to main (and this were part of the standard)? I don't see a problem here. In fact, it seems to me that this gives you more information (which could be used for optimization and the like)

要回答这个问题,我将再次转向C ++及其处理重载的方法。 C ++使用这种机制,几乎完全与所描述的一样,但有一个警告。 C ++没有标准化应如何实现其自身的某些部分,然后继续提出该遗漏的一些后果。特别是,C ++具有丰富的类型系统,其中包括虚拟类成员。该功能的实现方式由编译器编写者决定,vtable解析的细节对函数签名有很大的影响。由于这个原因,C ++特意建议编译器作者使名称修改在所有编译器之间或具有这些关键功能的不同实现的相同编译器之间相互不兼容。

To answer this, I will turn again to C++ and the way it deals with overloads. C++ uses this mechanism, almost exactly as described, but with one caveat. C++ does not standardize how certain parts of itself should be implemented, and then goes on to suggest how some of the consequences of that omission. In particular, C++ has a rich type system, that includes virtual class members. How this feature should be implemented is left to the compiler writers, and the details of vtable resolution has a strong effect on function signatures. For this reason, C++ deliberately suggests compiler writers make name mangling be mutually incompatible across compilers or same compilers with different implementations of these key features.

这只是一个更深层次问题的征兆,尽管诸如C ++和C之类的高级语言具有详细的类型系统,但较低级的机器代码却完全没有类型。任意丰富类型的系统都建立在机器级别提供的无类型二进制文件之上。链接器无权访问高级语言可用的丰富类型信息。链接器完全依赖于编译器来处理所有类型抽象并生成正确的无类型目标代码。

This is just a symptom of the deeper issue that while higher level languages like C++ and C have detailed type systems, the lower level machine code is totally typeless. arbitrarily rich type systems are built on top of the untyped binary provided at the machine level. Linkers do not have access to the rich type information available to the higher level languages. The linker is completely dependent on the compiler to handle all of the type abstractions and produce properly type-free object code.

C ++通过在变形对象名称中编码所有必需的类型信息来实现此目的。但是,C的目标明显不同,旨在成为一种便携式汇编语言。因此,C希望声明的名称与结果对象的符号名称之间具有严格的一对一对应关系。如果C缠住了它的名称,即使以一种标准化且可预测的方式,您也必须付出巨大的努力,以将更改后的名称与所需的符号名称进行匹配,否则就必须像在c ++中一样将其关闭。这种额外的努力几乎无济于事,因为与C ++不同,C的类型系统相当小而简单。

C++ does this by encoding all of the necessary type information in the mangled object names. C, however, has a significantly different focus, aiming to be a sort of portable assembly language. C prefers thus to have a strict one to one correspondence between the declared name and the resulting objects' symbol name. If C Mangled it's names, even in a standardized and predictable way, you would have to go to great efforts to match the altered names to the desired symbol names, or else you would have to turn it off as you do in c++. This extra effort comes at almost no benefit, because unlike C++, C's type system is fairly small and simple.

同时,定义几个类似命名的C函数(实际上只是作为参数的类型而异)实际上是一种标准做法。有关一个冗长的示例,请查看 OpenGL命名空间。

At the same time, it's practically a standard practice to define several similarly named C functions that vary only by the types they take as arguments. for a lengthy example of just this, have a look at the OpenGL namespace.

这篇关于C99不支持函数重载是有原因的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆