本文に進む 日本−日本語
日本HPホーム 製品とサービス お客様サポート/ ダウンロード ソリューション ご購入の方法
≫ お問い合わせ
詳細検索オプション
日本HPホーム
HP-UX リファレンス: セクション 5 : その他の機能 > v

varargs(5)

HP-UX 11i Version 2: September 2004
≫ 

テクニカル ドキュメント

PDF版
フィードバック
ここから本文が始まります

 ≫ 目次

 ≫ 索引

名称

varargs ― 可変個の引き数リストの取り扱い

構文

#include <varargs.h>

va_alist

va_dcl

void va_start(pvar)

va_list pvar;

type va_arg(pvar, type)

va_list pvar;

void va_end(pvar)

va_list pvar;

説明

この一連のマクロはプログラマ に移植可能な可変個の引き数リストを受け付けるプロシージャを書くことを可能にします。 可変個の引き数を持つ定期的な (例えば printf()) で varargs を使わないものは、異なったマシンでは異なった 引き数渡し規約 を使っているため、本来移植不可能です printf(3S) を参照してください)。

va_alist は関数ヘッダでパラメータ リストとして使われます。

va_dclva_alist の宣言です。 va_dcl の後にはセミコロンを付けてはいけません。

va_list はリストを走査していくために使われる変数用に定義された型です。

va_startpvar を初期化するために、リストの最初で呼び出されます。 argN の型は、関数の引き数リストの可変部分の直前の引き数と同じでなければなりません。

va_argpvar の指し示すリストの次の引き数を返します。 type は引き数に期待される型です。 異なった型を混ぜてもかまいませんが、どういう型の引き数が期待されているかを実行時に判別することはできませんので、それを知ることはルーチンの責任です。

va_end は終了処理を行います。

va_start ... va_end, で囲って複数の操作を行うこともできます。

注記: <varargs.h> ヘッダーファイルは、ANSI 以前のコンパイラおよび HP C/HP-UX の以前のリリースとの互換性を保つために提供されています。このファイルは、 varargs マクロをすべて含む <stdarg.h> に置き換えられています。

次の 例は execl() の実現方法です exec(2) を参照してください)。

#include <varargs.h> 
#define MAXARGS 100 
  
/*  execl is called by 
    execl(file, arg1, arg2, ..., (char *)0); 
*/ 
execl(va_alist) 
va_dcl 
{ 
      va_list ap; 
      char *file; 
      char *args[MAXARGS]; 
      int argno = 0; 
  
      va_start(ap); 
      file = va_arg(ap, char *); 
      while ((args[argno++] = va_arg(ap, char *)) != (char *)0); 
  
      va_end(ap); 
      return execv(file, args); 
} 

次の例は可変個の引き数 を受け取る関数が、その引き数をどのように他の関数に渡すことができるかを示しています。 これを実現するために、可変個の引き数リストを受け取る最初のルーチン (この例の log_errors()) が、 va_start() の返り値であるアドレス ポインタを、同じ可変個の 引き数リストにアクセスする必要のある それ以降の呼び出しに渡してやることが必要です。 このアドレス ポインタを受け取るすべてのルーチン (この例では v_print_log()) は単に va_arg() を使えば、そのルーチンがあたかも可変個の引き数を渡された元のルーチンであるかのように元の可変個の引き数リストにアクセスできます。

次の例では、他に同様のルーチン (例えば log_warning()log_message()) があり、それらもまた v_print_log() 関数を呼び出しているという状況を想像することができます。


#include <stdio.h>
#include <varargs.h>
#include <unistd.h>
 
int error_count;
 
/* VARARGS4 -- for lint */
int
log_errors(log_fp, func_name, err_num, msg_fmt, va_alist)
FILE *log_fp;
char *func_name;
int err_num;
char *msg_fmt;
va_dcl
{
 
    va_list ap;
 
    /* Print error header information */
    (void) fprintf(log_fp, "\nERROR in process %d\n", getpid());
    (void) fprintf(log_fp, "  function \"%s\": ", func_name);
    switch(err_num)
    {
        case ILLEGAL_OPTION:
            (void) fprintf(log_fp, "illegal option\n");
            break;
        case CANNOT_PARSE:
            (void) fprintf(log_fp, "cannot parse input file\n");
            break;
        ...
    }
 
   /*
    * Get pointer to first variable argument so that we can
    * pass it on to v_print_log().  We do this so that
    * v_print_log() can access the variable arguments passed
    * to this routine.
    */
    va_start(ap);
 
    v_print_log(log_fp, msg_fmt, ap);
 
    va_end(ap);
}
 
/* VARARGS2 -- for lint */
int
v_print_log(log_fp, fmt, ap)
FILE *log_fp;
char *fmt;
va_list ap;
{
 
    /*
     * If "%Y" is the first two characters in the format string,
     * a second file pointer has been passed in to print general
     * message information to.  The rest of the format string is
     * a standard  printf(3S) format string.
     */
    if ((*fmt == '%') && (*(fmt + 1) == 'Y'))
    {
        FILE *other_fp;
 
        fmt += 2;
 
        other_fp = (FILE *) va_arg(ap, char *);
        if (other_fp != (FILE *) NULL)
        {
            /*
             * Print general message information to additional stream.
             */
            (void) vfprintf(other_fp, fmt, ap);
            (void) fflush(other_fp);
        }
    }
 
    /*
     * Now print it to the log file.
     */
    (void) vfprintf(log_fp, fmt, ap);
}

警告

スタックフレームから引き数の個数を知ることは必ずしもできないため、それを指定するのは呼び出す側のルーチンの責任です。 例えば、 execl() ではリストの最後を知らせるためにゼロポインタが渡されています。 printf() はそのフォーマットからいくつの引き数があるかを判定することができます。

va_arg の引き数として char, short, や float を指定するのは移植性がよくありません。 これは呼び出された関数には引き数が charshort、 や float としては見えないからです。 C は関数に渡す前に charshort の引き数を int に変換し、 float の引き数を double, に変換してしまいます。

参照

exec(2)、 vprintf(3S)、 stdarg(5)

標準準拠

va_alist: AES, SVID2, SVID3, XPG2, XPG3, XPG4

va_arg: SVID2, SVID3, XPG2, XPG3, XPG4

va_dcl: SVID2, SVID3, XPG2, XPG3, XPG4

va_end: SVID2, SVID3, XPG2, XPG3, XPG4

va_list: SVID2, SVID3, XPG2, XPG3, XPG4

va_start: SVID2, SVID3, XPG2, XPG3, XPG4

<varargs.h>: AES, SVID3, XPG2, XPG3, XPG4

印刷用画面へ
プライバシー 本サイト利用時の合意事項
© 1983-2004 Hewlett-Packard Development Company, L.P.