c中具有不同类型参数的可变参数函数
variadic functions with different types of arguments in c
我想知道是否可以在 C 中创建一个接受不同类型参数的可变参数函数。即
void fillDatabase(char* name, int age){
writeToDatabase(name, age);
}
int main(){
fillDatabase("Paul", 19);
fillDatabase("Herbert");
}
我在这里尝试用姓名和年龄填充数据库。但也可以只填写姓名而不填写年龄。所以我想知道我是否可以为此使用相同的功能,或者我是否必须编写两个不同的功能?
Online 我只能找到具有相同参数类型的可变参数函数的示例。
提前致谢!
在 C99 中,可变参数函数使用 stdarg(3) 操作(通常实现为宏扩展到 编译器特定的 神奇的东西,例如 GCC 内置函数)。第一个参数应该有一些固定的已知类型,并且通常决定如何获取其他参数;在当今的几个 ABI 中,可变函数参数传递不使用寄存器,因此效率低于固定元数函数调用。
在你的情况下,你最好有几个函数。对于灵感,sqlite 有 several open functions.
请注意 POSIX 定义了一些带有一个 last 可选参数的函数,特别是 open(2)。这可能实现为具有无法提供 last 参数的函数。
您可以阅读针对您的实施的 ABI specification and the calling conventions。
顺便说一句,没有函数重载(就像在 C++ 中一样)可以理解为 C 的一个优点(函数名——这是唯一 linker care about, at least on Linux & Unix- determines its signature). Hence C++ practically needs name mangling. Read also about dynamic linking and dlopen
查看 va_list、va_start 等的手册页
您使用 ... 序列声明函数原型以表示变量 args:
void myfunction(FILE *, *fmt, ...);
例如,我们声明了一个 va_list 类型的结构(假设您包含了 stdarg):
struct va_list l;
在...之前使用参数初始化列表 - 我们会将 *fmt 指针传递给 va_start:
va_start(l, fmt);
现在,我们可以调用 va_arg 来获取一个值...如果我们正在处理格式字符串,我们可能会有这样的循环:
while (*fmt) {
/* Look for % format specifier... */
if (*fmt == '%') {
/* Following character can be c for char, i for int or f for float. */
// Opps - advance to char following opening %...
fmt++;
if (*fmt == 'c')
fprintf(stream, "%c", (char) va_arg(l, int));
else if (*fmt == 'i')
fprintf(stream, "%i", (int) va_arg(l, int));
else if (*fmt == 'f')
fprintf(stream, "%f", (float) va_arg(l, double));
... and so on...
您依靠 % 后面的字符来告诉您相应参数中期望的数据类型。建议您阅读 va_list.
的手册页
我想知道是否可以在 C 中创建一个接受不同类型参数的可变参数函数。即
void fillDatabase(char* name, int age){
writeToDatabase(name, age);
}
int main(){
fillDatabase("Paul", 19);
fillDatabase("Herbert");
}
我在这里尝试用姓名和年龄填充数据库。但也可以只填写姓名而不填写年龄。所以我想知道我是否可以为此使用相同的功能,或者我是否必须编写两个不同的功能?
Online 我只能找到具有相同参数类型的可变参数函数的示例。
提前致谢!
在 C99 中,可变参数函数使用 stdarg(3) 操作(通常实现为宏扩展到 编译器特定的 神奇的东西,例如 GCC 内置函数)。第一个参数应该有一些固定的已知类型,并且通常决定如何获取其他参数;在当今的几个 ABI 中,可变函数参数传递不使用寄存器,因此效率低于固定元数函数调用。
在你的情况下,你最好有几个函数。对于灵感,sqlite 有 several open functions.
请注意 POSIX 定义了一些带有一个 last 可选参数的函数,特别是 open(2)。这可能实现为具有无法提供 last 参数的函数。
您可以阅读针对您的实施的 ABI specification and the calling conventions。
顺便说一句,没有函数重载(就像在 C++ 中一样)可以理解为 C 的一个优点(函数名——这是唯一 linker care about, at least on Linux & Unix- determines its signature). Hence C++ practically needs name mangling. Read also about dynamic linking and dlopen
查看 va_list、va_start 等的手册页
您使用 ... 序列声明函数原型以表示变量 args:
void myfunction(FILE *, *fmt, ...);
例如,我们声明了一个 va_list 类型的结构(假设您包含了 stdarg):
struct va_list l;
在...之前使用参数初始化列表 - 我们会将 *fmt 指针传递给 va_start:
va_start(l, fmt);
现在,我们可以调用 va_arg 来获取一个值...如果我们正在处理格式字符串,我们可能会有这样的循环:
while (*fmt) {
/* Look for % format specifier... */
if (*fmt == '%') {
/* Following character can be c for char, i for int or f for float. */
// Opps - advance to char following opening %...
fmt++;
if (*fmt == 'c')
fprintf(stream, "%c", (char) va_arg(l, int));
else if (*fmt == 'i')
fprintf(stream, "%i", (int) va_arg(l, int));
else if (*fmt == 'f')
fprintf(stream, "%f", (float) va_arg(l, double));
... and so on...
您依靠 % 后面的字符来告诉您相应参数中期望的数据类型。建议您阅读 va_list.
的手册页