C中的函数重载
Posted
技术标签:
【中文标题】C中的函数重载【英文标题】:Function overloading in C 【发布时间】:2011-02-10 18:31:06 【问题描述】:今天,查看open()
的手册页,我注意到这个函数被“重载”了:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
我不认为这在 C 上是可能的。实现这一目标的“诀窍”是什么?
稍后编辑:
所以它并不是真正的重载,因为当使用可变参数时 - 你只能提供相同类型的多个参数。那么,mode_t
在幕后是 int 吗?
【问题讨论】:
mode_t 确实是一个整数,但您可以提供不同类型的参数,前提是您知道如何解释它们。 printf 系列函数就是这样做的,它使用格式字符串来知道如何解释它的额外参数,即使它们的类型不同。我在下面的回答有一些例子可以澄清这一点。 @Eli 谢谢,我一定把它和 Java 搞混了。 这样的函数称为可变参数函数。 【参考方案1】:它正在使用variable arguments。这些声明仅出现在手册页中,因为这两种方法是您应该调用 open() 的唯一方法。实际的 C 函数将被声明为例如
int open(const char *pathname,int flags,...);
对于可变参数,参数不需要是相同的类型。 printf
就是一个明显的例子。
在 open() 的情况下,如果 'flags
包含 O_CREAT 标志,则第一个变量参数必须是 mode_t,因为 open() 的实现期望它是 mode_t(在幕后可能是 unsigned int 或unsigned long - 但这与可变参数无关)
【讨论】:
【参考方案2】:C 确实可以使用variable number of argument 编写函数,例如printf
。
话虽如此,在 C 语言中没有可靠的、跨平台的方法来编写一个只需要 2 或 3 个参数的函数;一般来说,你必须做类似的事情
some_function(5, 6, 7, NULL);
some_function(5, 6, 8, 2, 5, NULL);
换句话说,你必须有一个终止的“sentinal”参数。或者,您可以以某种方式在较早的参数中包含参数的数量,例如
another_func(2, "hello", "world");
another_func(3, "goodbye", "cruel", "world");
printf
系列函数采用这种方法;第一个格式参数包含所需的额外参数的数量;例如printf("%f %f", 5.6, 7.11)
你知道必须有 2 个浮点参数。但是,这在用户定义的库函数中会有些不安全,因为如果您说my_printf("%s %f %f %f %s", 5.6)
,那么您可能会遇到段错误或更糟。幸运的是,大多数 C 编译器会在编译时检查您对 printf
的调用以避免此类问题。
在open
的情况下,函数被声明为具有可变参数,并且仅当设置了O_CREAT
时才检查第三个参数。所以这就是它“安全地”确定是否存在第三个参数的方式。我将“安全”放在引号中,因为从技术上讲,open 无法在运行时知道实际传递了多少参数。例如,以下调用编译时不会出现任何错误或警告:
open("foo.txt", 5, "not an integer", 7); // extra and invalid parameters
open("bar.txt", O_CREAT); // third parameter is missing
【讨论】:
如果some_function()
采用int
s,则不应以NULL
结尾,因为NULL
在数字上下文中只是0。 NULL
终结符最适合使用指针参数。
@Chris:很好,我通常使用 NULL 作为终止符,而不管数据类型如何,但你说得对,它可能会让人感到困惑,尤其是对于那些不知道 0 和 NULL 是同样,因为他们可能认为他们可以编写类似 some_func(3, 2, 1, 0, -1, NULL)
的东西,而实际上这会导致 0 充当终止参数。
最新版本的 gcc 和 glibc 标头一起会对您的最后两个示例产生警告。【参考方案3】:
"当 O_CREAT 在标志中时必须指定模式,否则将被忽略。"
extern int open (__const char *__file, int __oflag, ...)
它使用varargs
并且仅在__oflag
包含O_CREAT
时加载模式变量参数。
【讨论】:
【参考方案4】:非常简短的答案 - 可变参数
【讨论】:
并淘汰正确答案的反对票 - 简洁是一种美德。【参考方案5】:你可以使用带有...
的变量参数列表来伪造它
int function(int x, ...);
【讨论】:
以上是关于C中的函数重载的主要内容,如果未能解决你的问题,请参考以下文章