我正在努力调和我在C中创建可变函数的规则就在省略号之前总是一个int";。另一方面,我看到了很多示例程序,包括stackoverflow上的程序,它们没有提到这样的规则(或约定(,实际上在没有规则(或惯例(的情况下也能工作。(事实上,最常见的函数似乎是这样定义的:int myFunc(char *format, ...)
,用于sprintf
或朋友(。
我正试图了解它是如何工作的,以便未来的工作基于理解,而不是基于复制/粘贴的使用。目前,对我来说,这就像一根魔杖。因此,为了了解如何最大限度地利用这个选项,我需要了解规则。你能帮助我理解为什么我发现如此矛盾的要求,以及为什么这两种约定似乎都有效吗?
谢谢。
关于变元函数的主要规则是,您需要某种方法来确定您有多少个参数以及这些参数的类型,尽管不一定像教程中所说的那样。
一般来说,有两种方法:一个固定参数告诉可变参数的数量和类型,或者一个可变参数是指定参数列表结尾的sentinel值。
来自标准库和POSIX的示例:
printf
和族:第一个参数是一个格式字符串,该格式字符串的内容指定每个变参数的数量和类型execl
:它的两个固定参数中的第二个是要运行的外部程序的第一个参数。如果它不是NULL,可变参数将被读取为类型const char *
,直到它找到一个NULL
第一个选项的变体如您所述:其中一个固定参数是可变参数的数量,其中每个可变参数都具有相同的预定类型。这是最简单的实现方式,这可能就是你链接的教程建议它的原因
您选择哪一个完全取决于您的用例。
另一个有趣的变体是Linux和类似系统上的open
函数。手册页显示以下签名:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
实际声明如下:
extern int open (const char *__file, int __oflag, ...) __nonnull ((1));
在这种情况下,如果flags
参数包括值O_CREAT
,则读取一个变参数。
在C标准中没有规则规定函数声明中...
之前的参数必须是int
。您链接到的文章只是指它的特定示例:当一个函数用(int foo, ...)
声明时,传递给该特定函数的第一个参数(从实际参数转换后;例如,char
参数将转换为int
(始终是int
。
通常,...
之前的参数可以有任何类型。唯一的规则是...
之前必须至少有一个显式参数。