【问题标题】:Enforcing ending variadic function parameters with NULL强制使用 NULL 结束可变参数函数参数
【发布时间】:2017-03-23 18:34:40
【问题描述】:

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

今天我从 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。这个可能通常会让我休息,第一个是对学生的简化,第二个是一个 varning,这是真实的(尽管我通常可能会更重视选项一和二。)

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

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

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

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

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

【问题讨论】:

  • 不清楚您的要求。 ... 必须是参数列表中的最后一个。 1)肯定是错误的,2)是有效的——作为一个小任务:研究原因。而NULL 是一个宏,而不是一个字符。

标签: c exec variadic-functions unistd.h


【解决方案1】:

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

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

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

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

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

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


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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2020-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-21
        相关资源
        最近更新 更多