是否需要在具有多个“return”语句的可变函数中的每个“return”语句之前调用“va_end()”?
Does `va_end()` need to be invoked before each `return` statement in a variadic function with multiple `return` statements?
关于va_end()
,有一件事总是让我困惑。我经常读到这不是一个实际的函数,而是一个预处理器宏。虽然这听起来像是一个微不足道的细节,但它实际上会影响需要调用 va_end()
的位置。
问题很简单:是否需要在具有多个 return
语句的可变参数函数中的每个 return
语句之前调用 va_end()
?
以下示例中的可变参数函数的任务很简单,即返回其参数的第一个非 NULL
。如您所见,函数体中有三个 return
语句。其中之一出现在 va_start()
之后但在 va_end()
.
之前
此代码正确吗?
#include <stdio.h>
#include <stdarg.h>
static const void * const FIRST_NON_NULL_END = (void *) "";
void * first_non_null (
const void * const ptr1,
...
) {
if (ptr1) {
return ptr1 == FIRST_NON_NULL_END ? NULL : (void *) ptr1;
}
void * retval;
va_list args;
va_start(args, ptr1);
do {
retval = va_arg(args, void *);
if (retval == FIRST_NON_NULL_END) {
/* Is this correct? Here I do not invoke `va_end()`! */
return NULL;
}
} while (!retval);
va_end(args);
return retval;
}
int main () {
const char * const my_string = first_non_null(
NULL,
NULL,
"autumn",
NULL,
"rose",
FIRST_NON_NULL_END
);
printf("The first non-null value is: \"%s\".\n", my_string);
return 0;
}
编辑:
澄清一下,上面的示例是以这种形式编写的,仅用于教学目的。在现实生活中,它可以用更好的合成方式重写为:
#include <stdio.h>
#include <stdarg.h>
static const void * const FIRST_NON_NULL_END = (void *) "";
void * first_non_null (
const void * const ptr1,
...
) {
const void * retval;
va_list args;
va_start(args, ptr1);
for (retval = ptr1; !retval; retval = va_arg(args, const void *))
;;
va_end(args);
return retval == FIRST_NON_NULL_END ? NULL : (void *) retval;
}
int main () {
const char * const my_string = first_non_null(
NULL,
NULL,
"autumn",
NULL,
"rose",
FIRST_NON_NULL_END
);
printf("The first non-null value is: \"%s\".\n", my_string);
return 0;
}
来自 C 标准(7.16.1 可变参数列表访问宏)
1 ... Each invocation of the va_start and va_copy macros shall be matched
by a corresponding invocation of the va_end macro in the same
function.
因此,如果 va_start
在任何 return 语句之前使用并且 va_end
尚未被调用,则应调用它。
关于va_end()
,有一件事总是让我困惑。我经常读到这不是一个实际的函数,而是一个预处理器宏。虽然这听起来像是一个微不足道的细节,但它实际上会影响需要调用 va_end()
的位置。
问题很简单:是否需要在具有多个 return
语句的可变参数函数中的每个 return
语句之前调用 va_end()
?
以下示例中的可变参数函数的任务很简单,即返回其参数的第一个非 NULL
。如您所见,函数体中有三个 return
语句。其中之一出现在 va_start()
之后但在 va_end()
.
此代码正确吗?
#include <stdio.h>
#include <stdarg.h>
static const void * const FIRST_NON_NULL_END = (void *) "";
void * first_non_null (
const void * const ptr1,
...
) {
if (ptr1) {
return ptr1 == FIRST_NON_NULL_END ? NULL : (void *) ptr1;
}
void * retval;
va_list args;
va_start(args, ptr1);
do {
retval = va_arg(args, void *);
if (retval == FIRST_NON_NULL_END) {
/* Is this correct? Here I do not invoke `va_end()`! */
return NULL;
}
} while (!retval);
va_end(args);
return retval;
}
int main () {
const char * const my_string = first_non_null(
NULL,
NULL,
"autumn",
NULL,
"rose",
FIRST_NON_NULL_END
);
printf("The first non-null value is: \"%s\".\n", my_string);
return 0;
}
编辑:
澄清一下,上面的示例是以这种形式编写的,仅用于教学目的。在现实生活中,它可以用更好的合成方式重写为:
#include <stdio.h>
#include <stdarg.h>
static const void * const FIRST_NON_NULL_END = (void *) "";
void * first_non_null (
const void * const ptr1,
...
) {
const void * retval;
va_list args;
va_start(args, ptr1);
for (retval = ptr1; !retval; retval = va_arg(args, const void *))
;;
va_end(args);
return retval == FIRST_NON_NULL_END ? NULL : (void *) retval;
}
int main () {
const char * const my_string = first_non_null(
NULL,
NULL,
"autumn",
NULL,
"rose",
FIRST_NON_NULL_END
);
printf("The first non-null value is: \"%s\".\n", my_string);
return 0;
}
来自 C 标准(7.16.1 可变参数列表访问宏)
1 ... Each invocation of the va_start and va_copy macros shall be matched by a corresponding invocation of the va_end macro in the same function.
因此,如果 va_start
在任何 return 语句之前使用并且 va_end
尚未被调用,则应调用它。