使用 NULL 强制结束可变函数参数
Enforcing ending variadic function parameters with 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, ...);
是我找到的 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。
可变参数函数的声明只能指定所需的参数,编译器可以强制执行它们的类型。可变长度部分从未进行过任何类型检查。可变长度部分总是在最后。 execle()
的声明并不意味着真正的 C 声明,而只是向程序员描述他应该如何构造参数。
无法强制 execl()
的最后一个参数是 NULL
。可变参数函数不知道提供了多少参数,它们根据参数的值来确定。 printf()
假设它有足够的参数来填充格式字符串中的所有运算符,并且 execl()
遍历参数直到找到 NULL
(execle()
类似,但是它读取一个额外的参数以获得 envp
)。如果你不以 NULL
结尾,它会继续前进,读取垃圾并导致未定义的行为。
Is it possible to make declaration of variadic function so that it doesn't end with "..."?
这可能吗 是一个狡猾的问题,但请考虑以下事实:
- 标准说 "If a function that accepts a variable number of arguments is defined without a parameter type list that ends with the ellipsis notation, the behavior is undefined" (C2011, 6.9.1/8)
也许这已经回答了这个问题,但如果您选择含糊其词并专注于 不是 定义的函数声明,那么
- 函数定义也是声明
- C 语言标准要求同一函数的所有声明都是 "compatible"(否则程序行为未定义)(C2011 6.7/4)
- 参数列表不匹配的两个函数声明不兼容(C2011、6.2.7/3)
因此,如果您声明了一个实际上也已定义的可变函数,并且该函数的参数列表没有 end 和 ...
,那么程序的行为是未定义。
您阅读的有关 execle()
和 execl()
的文档是为了表达和讨论这些函数的期望而编写的,但在某种程度上它似乎提供了可变函数声明,其中参数列表的最后一个元素不是 ...
,它们实际上不是有效的 C 函数声明。
So finally, is it possible to make variadic functions ending with a NULL characters (execl) and if not, is it possible to make it end with predefined variable (execle)?
无法通过符合 C 的声明来描述此类调用约定。可变参数函数可以有这样的期望,并且可以在运行时强制执行它们,但它们只能在编译时由依赖于所涉及函数的特殊知识的编译器或允许描述此类约束的 C 语言扩展来强制执行。
您看到的声明是execl 手册页中的声明。 glib 中 execle 的声明如下:int execle (const char *path, const char *arg, ...)
。该实现假定最后一个参数是一个 char**,并将其用于 envp。我不认为你可以在 C 中强制执行这样的规则。
是否可以声明可变函数,使其不以“...”结尾?
今天我从 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。
可变参数函数的声明只能指定所需的参数,编译器可以强制执行它们的类型。可变长度部分从未进行过任何类型检查。可变长度部分总是在最后。 execle()
的声明并不意味着真正的 C 声明,而只是向程序员描述他应该如何构造参数。
无法强制 execl()
的最后一个参数是 NULL
。可变参数函数不知道提供了多少参数,它们根据参数的值来确定。 printf()
假设它有足够的参数来填充格式字符串中的所有运算符,并且 execl()
遍历参数直到找到 NULL
(execle()
类似,但是它读取一个额外的参数以获得 envp
)。如果你不以 NULL
结尾,它会继续前进,读取垃圾并导致未定义的行为。
Is it possible to make declaration of variadic function so that it doesn't end with "..."?
这可能吗 是一个狡猾的问题,但请考虑以下事实:
- 标准说 "If a function that accepts a variable number of arguments is defined without a parameter type list that ends with the ellipsis notation, the behavior is undefined" (C2011, 6.9.1/8)
也许这已经回答了这个问题,但如果您选择含糊其词并专注于 不是 定义的函数声明,那么
- 函数定义也是声明
- C 语言标准要求同一函数的所有声明都是 "compatible"(否则程序行为未定义)(C2011 6.7/4)
- 参数列表不匹配的两个函数声明不兼容(C2011、6.2.7/3)
因此,如果您声明了一个实际上也已定义的可变函数,并且该函数的参数列表没有 end 和 ...
,那么程序的行为是未定义。
您阅读的有关 execle()
和 execl()
的文档是为了表达和讨论这些函数的期望而编写的,但在某种程度上它似乎提供了可变函数声明,其中参数列表的最后一个元素不是 ...
,它们实际上不是有效的 C 函数声明。
So finally, is it possible to make variadic functions ending with a NULL characters (execl) and if not, is it possible to make it end with predefined variable (execle)?
无法通过符合 C 的声明来描述此类调用约定。可变参数函数可以有这样的期望,并且可以在运行时强制执行它们,但它们只能在编译时由依赖于所涉及函数的特殊知识的编译器或允许描述此类约束的 C 语言扩展来强制执行。
您看到的声明是execl 手册页中的声明。 glib 中 execle 的声明如下:int execle (const char *path, const char *arg, ...)
。该实现假定最后一个参数是一个 char**,并将其用于 envp。我不认为你可以在 C 中强制执行这样的规则。