使用终结符值来确定 va 列表的结尾

对于任何可变参数函数,该函数必须知道如何解释变量参数列表。 传统方法(以 printf 为例)是指定前面的参数数量。但是,这并不总是一个好主意:

/* First argument specifies the number of parameters; the remainder are also int */
extern int sum(int n, ...);

/* But it's far from obvious from the code. */
sum(5, 2, 1, 4, 3, 6)

/* What happens if i.e. one argument is removed later on? */
sum(5, 2, 1, 3, 6)  /* Disaster */

有时,添加显式终结符会更加健壮,例如 POSIX execlp() 函数。这是计算一系列 double 数字之和的另一个函数:

#include <stdarg.h>
#include <stdio.h>
#include <math.h>

/* Sums args up until the terminator NAN */
double sum (double x, ...) {
  double sum = 0;
  va_list va;

  va_start(va, x);
  for (; !isnan(x); x = va_arg(va, double)) {
    sum += x;
  }
  va_end(va);

  return sum;
}

int main (void) {
  printf("%g\n", sum(5., 2., 1., 4., 3., 6., NAN));
  printf("%g\n", sum(1, 0.5, 0.25, 0.125, 0.0625, 0.03125, NAN));
}

良好的终结者值:

  • 整数(假设全部为正或非负) - 0-1
  • 浮点类型 - NAN
  • 指针类型 - NULL
  • 枚举器类型 - 一些特殊值