使用NULL强制结束可变参数函数参数

时间:2017-03-23 18:34:41

标签: c exec variadic-functions unistd.h

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

今天我从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, ...);是我找到的here。这个可能通常会让我休息,第一个是学生的简化,第二个是变化,这是真实的(尽管我可能通常会更加关注选项一和二。)

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

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

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

最后,是否可以使用NULL字符(execl)结束变量函数,如果没有,是否可以使用预定义变量(execle)结束?

我尝试用gcc 6.3.1编译,我也试过--std = c11。

3 个答案:

答案 0 :(得分:4)

  

是否可以声明可变函数,以便它不会以" ..."?

结束

是否可能是一个滑稽的问题,但请考虑以下事实:

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

也许这已经回答了这个问题,但如果你选择缩小词汇并专注于定义的函数声明,那么

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

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

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

  

最后,是否可以使用NULL字符(execl)结束变量函数,如果没有,是否可以使用预定义变量(execle)结束?

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

答案 1 :(得分:1)

可变参数函数的声明只能指定必需的参数,编译器可以强制执行它们的类型。可变长度部分从不进行任何类型检查。可变长度部分总是在最后。 execle()的声明并不是一个真正的C声明,而只是向程序员描述他应该如何构造参数。

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

答案 2 :(得分:1)

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