C语言 使用 NULL 强制执行结束可变参数函数参数



是否可以声明可变参数函数,使其不以"..."结尾?

今天我从unistd.h学到了更多关于exec的信息,但整天我看到了三个(实际上是两个)不同的execl声明:

1)int execl ( const char * path, const char * arg0, ..., (char*)NULL );在学校向我们展示的,我想我将不得不以NULL 值结束函数调用

2)int execl(const char *path, const char *arg, ... /* (char *) NULL */);是我在 exec(3) 手册页中找到的。这可能意味着我仍然必须以 NULL 值结束它,但它不是强制执行的。

3)int execl(const char *path, const char *arg, ...);是我在这里找到的。这个通常会让我休息,第一个是学生的简化,第二个是变种,这是真实的事情(尽管我通常会更重视选项一和选项二。

但后来我在同一网站上发现了这个声明:

int execle(const char *path, const char *arg, ..., char * const envp[]);

同样的问题适用,我无法创建不以...结尾的可变参数函数,gcc 告诉我它期待')' before ',' token指向三个点后的逗号。

所以最后,是否可以使可变参数函数以 NULL 字符 (execl) 结尾,如果不能,是否可以使其以预定义变量 (execle) 结尾?

我尝试使用 gcc 6.3.1 进行编译,我也尝试了 --std=c11。

是否可以声明可变参数函数,使其不以"..."结尾?

是否有可能是一个棘手的问题,但请考虑以下事实:

  • 该标准说:"如果定义接受可变数量参数的函数时没有以省略号表示法结尾的参数类型列表,则行为未定义"(C2011,6.9.1/8)

也许这已经回答了这个问题,但是如果您选择切碎单词并专注于不是定义的函数声明,那么

  • 函数定义也是声明
  • C 语言标准要求同一函数的所有声明都是"兼容的"(否则程序行为是未定义的)(C2011 6.7/4)
  • 参数列表不匹配的两个函数声明不兼容 (C2011, 6.2.7/3)

因此,如果你声明了一个可变参数函数,实际上也是定义的,并且该函数的参数列表不以...结尾,那么程序的行为是未定义的。


您一直在阅读execle()execl()的文档是为了表达和讨论这些函数的期望而编写的,但在某种程度上,它似乎提供了可变参数函数声明,其中参数列表的最后一个元素未...,这些实际上不是有效的 C 函数声明。

所以最后,是否可以使可变参数函数以 NULL 字符 (execl) 结尾,如果不能,是否可以使其以预定义变量 (execle) 结尾?

不可能通过符合 C 的声明来描述此类调用约定。 可变参数函数可以有这样的期望,并且可以在运行时强制执行它们,但它们只能在编译时由依赖于所涉及函数的特殊知识的编译器或允许描述此类约束的 C 语言扩展强制执行。

可变参数函数的声明只能指定所需的参数,编译器可以强制执行它们的类型。可变长度部分从不进行任何类型检查。可变长度部分始终位于末尾。execle()的声明并不是一个实际的 C 声明,而只是向程序员描述他应该如何构造参数。

不可能强制execl()的最后一个参数是NULL。可变参数函数不知道提供了多少参数,它们根据参数的值确定它。printf()假设它有足够的参数来填充格式字符串中的所有运算符,并且execl()遍历参数,直到找到NULL(execle()类似,但它读取一个额外的参数来获取envp)。如果你不以NULL结尾,它只会继续前进,读取垃圾并导致未定义的行为。

您看到的声明是 execl 手册页中的声明。在 glib 中对 execle 的声明如下:int execle (const char *path, const char *arg, ...)。该实现假定最后一个参数是 char**,并将其用于 envp。我不认为你可以在 C 中强制执行这样的规则。

最新更新