可変引数関数

C/C++セキュアコーディングを読んでのメモ.



前から気になってたけど, ちょうど良い機会なので調べてみる(というか本のサンプルをちょっと改変).
#includeを宣言する

  • 可変リストの引数に対しては型検査は行われない
  • 省略記号は, 引数リストの最後の要素でなければならない(1つ以上の固定パラメータは, 省略記号の前に記載する)
  • 可変引数リストの終端は, プログラマと関数の利用者との間の決め事による

省略記号は, 「...」で表される.


サンプルにこんなの組んでみた.
単純な足し算プログラム.

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

int sum( int first, ... );

int main( int argc, char *argv[] )
{
  int n1 = 5;
  int n2 = 10;
  int n3 = 15;
  int n4 = 20;
  int n5 = 95;

  printf( "%d + %d = %d\n",           n1, n2, sum( n1, n2, -1 ) );
  printf( "%d + %d + %d = %d\n",      n1, n2, n3, sum( n1, n2, n3, -1 ) );
  printf( "%d + %d + %d + %d = %d\n", n1, n2, n3, n4, sum( n1, n2, n3, n4, -1 ) );
  printf( "%d + %d + %d + %d + %d = %d\n", n1, n2, n3, n4, n5, sum( n1, n2, n3, n4, n5, -1 ) );

  return 0;
}


int sum( int first, ... )
{
  int num = 0;
  int sum = 0;
  va_list mark;

  /* 固定引数firstは, va_start()が最初の可変引数の位置を知るために使用 */
  va_start( mark, first );
  while( num != -1 ){
    sum += num;
    /* va_arg()マクロは, 引数に指定された型のサイズに基いて引数ポインタを進める */
    num = va_arg( mark, int );
  }
  /* 後始末 */
  va_end( mark );

  return sum;
}

関数sumの引数の最後を「-1」にしなかったら, セグメントエラーが出て終了する.
実行結果.

[khiker@khlin001 ~/<1>c/secure]$ gcc -Wall test_stdarg.c -o test_stdarg
[khiker@khlin001 ~/<1>c/secure]$ ./test_stdarg
5 + 10 = 10
5 + 10 + 15 = 25
5 + 10 + 15 + 20 = 45
5 + 10 + 15 + 20 + 95 = 140

今回は, 引数に取るのをintだけにしたから簡単だったけど, printfみたいなのだったら大変なんだろうなあと思う.