我有一个功能foo(char *n, ...);
我需要获取并使用所有可选的char
参数。
我有个想法使用
while(va_arg(argPtr, char) != NULL)
{
...
}
了解何时到达列表末尾。那么,它是否有效,如果在函数调用中我将foo(n, 't', 'm', '$', NULL);
?
va_arg会将NULL
读为char吗?
或者可能有更常用的方法来确定列表的结尾,而不是添加NULL
作为最后一个参数?
答案 0 :(得分:7)
对于使用va_arg
来确定给定调用传递的参数的数量或类型的函数,没有直接方式。
特别提出的建议方法:
while(va_arg(argPtr, char) != NULL)
不正确。 va_arg(argPtr, char)
生成类型char
的值,而NULL
是空指针常量。 (NULL
通常定义为0
,它与空字符'\0'
进行比较,但您不能依赖它。)
任何可变参数函数都必须让调用者指定参数的数量和类型。例如,*printf
函数通过(非可变参数)格式字符串执行此操作。 POSIX execl*()
函数需要一系列char*
个参数;参数列表的末尾由调用者(char*)NULL
标记。其他方法也是可能的,但它们几乎都依赖于参数中运行时给出的信息。 (你可以使用其他方法,例如全局变量。请不要。)
这会给调用者带来负担,以确保传递给函数的参数是一致的。该功能本身无法确认这一点。不正确的来电,例如printf("%d\n", "hello")
或execlp("name", "arg1")
,未定义的行为。
还有一件事:您不能将va_arg
与char
类型的参数一起使用。当您调用可变参数函数时,与, ...
对应的参数将提升。窄于int
的类型的整数参数将提升为int
或unsigned int
,类型float
的参数将提升为double
。如果调用者传递类型为char
的参数,则该函数必须调用va_arg(argPtr, int)
。
(在非常模糊的情况下,您不太可能遇到char
,unsigned int
可以提升为char
。只有当sizeof (int) == 1
无符号且{{1}这意味着一个字节至少是16位。)
答案 1 :(得分:1)
基本想法会起作用。但是你已经以几乎肯定不会赢得的方式填写了细节。
当您使用可变参数时,通常的隐式转换规则不适用。相反,会发生默认参数提升,这意味着任何小于int
/ unsigned int
的整数类型都会转换为其中一种 - 这不是唯一的促销,但这里唯一相关的 - 也意味着没有自动转换为您使用va_arg
指定的任何类型。
这意味着:
va_arg(..., char)
,因为将char
作为可变参数函数参数传递是不可能的。NULL
作为可变参数函数传递,因为它的具体类型与实现有很大关系。现实类型包括int
,long
,void *
,还有其他不太现实但同样有效的类型。你可以改变
while(va_arg(argPtr, char) != NULL)
到
while(va_arg(argPtr, int) != 0)
和电话
foo(n, 't', 'm', '$', NULL);
到
foo(n, 't', 'm', '$', 0);