今天我查看了open()
的man页,发现这个函数是“重载”的:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
我没想到在 C 语言中这是可能的。实现它的“技巧”是什么?
稍后编辑:
所以这并不是真正的重载,因为使用可变参数时,只能提供相同类型的多个参数。那么,在幕后,mode_t 是 int 吗?今天我查看了open()
的man页,发现这个函数是“重载”的:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
我没想到在 C 语言中这是可能的。实现它的“技巧”是什么?
稍后编辑:
所以这并不是真正的重载,因为使用可变参数时,只能提供相同类型的多个参数。那么,在幕后,mode_t 是 int 吗?它正在使用可变参数。这些声明仅出现在man页面中,因为这2种方法是您应该调用open()的唯一方式。实际的C函数将被声明为例如:
int open(const char *pathname,int flags,...);
使用可变参数时,参数的类型不需要相同。 printf
就是一个明显的例子。
在使用 open() 函数时,如果 'flags
' 参数包含 O_CREAT 标志,则第一个可变参数必须为 mode_t,因为 open() 的实现希望它是 mode_t 类型(在幕后可能是 unsigned int 或 unsigned long 类型,但这与可变参数无关)。
C语言确实可以编写具有可变数量参数的函数,例如printf
。
话虽如此,在C语言中没有可靠的、跨平台的方法来编写只带有2或3个参数的函数;通常你必须像这样做:
some_function(5, 6, 7, NULL);
some_function(5, 6, 8, 2, 5, NULL);
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)
,那么您可能会得到segfault或更糟的情况。幸运的是,大多数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
类型,就不应该以 NULL
结尾,因为在数值上下文中 NULL
只是 0。NULL
终止符最适用于指针参数。 - Chris Lutzsome_func(3, 2, 1, 0, -1, NULL)
的代码,而实际上这将导致0充当终止参数。 - Eli CourtwrightO_CREAT
在标志中时,必须指定模式,否则将被忽略。
extern int open (__const char *__file, int __oflag, ...)
使用可变参数列表,并且仅在 __oflag
包含 O_CREAT
时才加载模式变量参数。您可以使用变量参数列表和 ...
来模拟它。
int function(int x, ...);