澄清 c 程序中变量参数的要求
Clarification of requirements for variable arguments in c program
我试图调和我找到的在 C 中创建可变参数函数的规则。一方面,我看到明确声明(例如,here)语句,如“就在省略号始终是一个 int”。另一方面,我看到很多示例程序,包括在 Whosebug 上没有提到这样的规则(或约定),实际上没有它也能工作。而且我看到许多其他形式(额外的 int)似乎也有效。 (最常见的功能,实际上似乎是这样定义的:int myFunc(char *format, ...)
并与 sprintf
或朋友一起使用)。
我正在努力思考它是如何工作的,以便未来的工作基于理解,而不是基于 copy/paste 的使用。目前,对我来说,它还不如是一根魔杖。因此,为了了解如何充分利用该选项,我需要了解规则。你能帮我理解为什么我发现这些相互矛盾的要求以及为什么这两种约定似乎都有效吗?
谢谢。
关于可变参数函数的主要规则是你需要一些方法来确定你有多少参数以及这些参数的类型,尽管不一定是教程说。
通常有两种方法:固定参数之一告诉您可变参数的数量和类型,或者可变参数之一是指定参数列表末尾的标记值。
来自标准库的示例和 POSIX:
printf
and family: 第一个参数是一个格式字符串,这个格式字符串的内容指定了每个可变参数的数量和类型。
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
。您 link 阅读的文章仅指其特定示例:当使用 (int foo, ...)
声明函数时,第一个参数传递给该特定函数(在从实际参数转换后;例如, char
参数将转换为 int
) 始终是 int
.
一般来说,...
之前的参数可以是任意类型。唯一的规则是 ...
.
之前必须至少有一个显式参数
我试图调和我找到的在 C 中创建可变参数函数的规则。一方面,我看到明确声明(例如,here)语句,如“就在省略号始终是一个 int”。另一方面,我看到很多示例程序,包括在 Whosebug 上没有提到这样的规则(或约定),实际上没有它也能工作。而且我看到许多其他形式(额外的 int)似乎也有效。 (最常见的功能,实际上似乎是这样定义的:int myFunc(char *format, ...)
并与 sprintf
或朋友一起使用)。
我正在努力思考它是如何工作的,以便未来的工作基于理解,而不是基于 copy/paste 的使用。目前,对我来说,它还不如是一根魔杖。因此,为了了解如何充分利用该选项,我需要了解规则。你能帮我理解为什么我发现这些相互矛盾的要求以及为什么这两种约定似乎都有效吗?
谢谢。
关于可变参数函数的主要规则是你需要一些方法来确定你有多少参数以及这些参数的类型,尽管不一定是教程说。
通常有两种方法:固定参数之一告诉您可变参数的数量和类型,或者可变参数之一是指定参数列表末尾的标记值。
来自标准库的示例和 POSIX:
printf
and family: 第一个参数是一个格式字符串,这个格式字符串的内容指定了每个可变参数的数量和类型。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
。您 link 阅读的文章仅指其特定示例:当使用 (int foo, ...)
声明函数时,第一个参数传递给该特定函数(在从实际参数转换后;例如, char
参数将转换为 int
) 始终是 int
.
一般来说,...
之前的参数可以是任意类型。唯一的规则是 ...
.