如何处理C语言中的重复函数名?

25

我有一个小项目,其中我在两个不同的源文件中命名了两个相同名称的函数,在构建项目时编译器出现错误,提示“func_name已经在filename.obj中定义”。

为什么我不能在两个不同的源文件中有两个同名函数?我认为只有在头文件中声明函数时,它才会成为全局函数,否则函数应该只在源文件中可用。

除了更改文件名之外,C语言中是否还有其他优雅的解决重复函数名称的方法?


这就是为什么我总是使用真正有意义的变量和函数名称。如果这两个函数执行的是完全相同的操作,则您不需要其中一个。如果它们执行不同的操作,则为每个函数赋予一个反映其功能的有意义的名称。维护您的代码的人会感激您的。很可能,那个人就是您自己。 - Mawg says reinstate Monica
5个回答

49

C语言中,默认情况下,函数具有全局作用域。为了限制其范围,请使用 static 关键字将其私有化到模块内部。

头文件的作用仅仅是向其他模块公开该函数及其签名。

所有全局名称必须(在某些情况下)唯一。这是有道理的,因为该名称是链接器用来将函数调用与函数本身的实现连接起来的。

具有静态和局部作用域的名称只需要在其作用域内是唯一的。


12
建议:尽可能将每个函数标记为“static”。这也会让编译器的优化器更容易选择内联函数等操作。 - u0b34a0f6ae

17
无论某个东西是在头文件中声明还是在源文件中声明,对于编译器来说都没有任何区别。事实上,编译器本身完全不知道任何“头文件”,因为所谓的预处理器会将头文件嵌入到源文件中,在编译器真正工作之前完成其工作。当带有所有嵌入式头文件的源文件被送到实际的编译器时,就无法判断原始内容和从头文件中插入的内容。将所有头文件嵌入到源文件中的源文件称为翻译单元。也就是说,编译器正确地处理翻译单元,而不是一些“源”或“头”文件。
在C语言中,所有在文件范围内声明的对象和函数默认具有外部链接性,这意味着它们是全局的,在整个程序中是唯一的。所以,你的想法是不正确的。函数不仅限于一个源文件。
如果您想使函数(或对象)仅限于单个翻译单元,则必须采取一些明确的步骤。您必须将其声明为静态。将其声明为静态将赋予其内部链接性,这基本上意味着它变成了其翻译单元的内部函数。
将函数声明为静态只有在两者确实必须局限于自己的翻译单元时才有效。如果不是这种情况,即如果至少有一个函数应为全局可访问(可链接)函数,则别无选择,只能重命名其中一个函数。

8
为什么我不能在两个不同的源文件中有相同名称的两个函数?
因为链接器需要知道你引用哪个函数。
想象一下a.h和b.h都声明了my_function(),编译器会为两者生成代码。现在,假设c.c调用my_function(),链接器如何知道应该调用哪个版本的函数呢?

5

将函数声明为static可使其局限于文件内。在C语言中,每个标识符名称必须是唯一的。


4
优雅的解决方案是C++中引入的命名空间。如果 func_name 调用次数较少,则可以采取一种方法,即将其更名并重新编译。
某些黑客式但快速的解决方案可能是这样的:
//In one of the two source files and any file that calls it

//if your functions is something like this
//void func_name(int) { ... }
//Add the following line
#define func_name SOME_UNIQUE_FUNC_NAME

4
根据RBerteig的建议,声明静态变量是最好的解决方案。我留下我的答案,希望它能对某人有所帮助。 - user347594
这对我遇到的类似问题非常有帮助。谢谢。 - Canatto Filipe

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