C言語で可変個の引数を使うときには「stdarg.h」のマクロを使うと思います。x86系CPUでは普通変数をスタックに積んで関数を呼び出します(高速な呼び出しのためにレジスタで行う場合もあります)。つまりx86系CPUを対象としたこのマクロでやっていることはポインタ演算になるわけです。
ボーランドとマイクロソフトのヘッダとライブラリに感謝します。
まずはこのヘッダの中身を知らなければいけません。
アドレス演算をするためにはそれぞれの型のサイズを知る必要があります。そして、ソースコードを読む限り引数のサイズはintのサイズ以上なのです。というわけで以下のようなマクロを先に定義しておきます。
#define __va_size(x) ((sizeof(x) + sizeof(int) - 1) & ~(sizeof(int) - 1))
いわゆる切り上げをやっています。
「last」では最後の引数を取ります。
#define va_start(ap,last) (ap = (va_list)((char *)(&last) + __va_size(last)))
自分のスタックアドレスに自分のサイズを足して次の値を取り出せるようにしています。
今度は値の取り出しです。
#define va_arg(ap, type) (*(type *)((ap += __va_size(type)) - (__va_size(type))))
こんな感じです。
コレは一番簡単です。
#define va_end(ap) ((void)0)
本当に申し訳ないんですが、手元のヘッダファイルにはコレが載っていませんでした。まあ、上の三つで代用できるので今回はパスです。
とりあえず上のをまとめたものに色々足します。
/* 標準ライブラリ(stdarg.h)*/ /* 可変個の引数をサポートをする。 ver1.0 作成者(auther):利都(Rito) 作成日(make):2006-4-15 http://www.atelier-blue.com/ mail:webmaster@atelier-blue.com */ #ifndef __INC_STDARG_H #define __INC_STDARG_H typedef char * va_list; #define __va_size(x) ((sizeof(x) + sizeof(int) - 1) & ~(sizeof(int) - 1)) #define va_start(ap,last) (ap = (va_list)((char *)(&last) + __va_size(last))) #define va_arg(ap, type) (*(type *)((ap += __va_size(type)) - (__va_size(type)))) #define va_end(ap) ((void)0) #endif
あなたの環境で動くかは保証できませんが、興味のある方は試してみてください。下がテスト用のソースコードです(本当はもっと色々な引数で試してみないといけませんね)。
#include <stdio.h> #include <stdarg.h> /* 標準ライブラリ(stdarg-t.h)*/ /* 可変個の引数をサポートをする「stdarg」のテスト用ヘッダ。 ver1.0 作成者(auther):利都(Rito) 作成日(make):2006-4-15 http://www.atelier-blue.com/ mail:webmaster@atelier-blue.com */ #ifndef __INC_STDARG_H #define __INC_STDARG_H typedef char * va_list_t; #define __va_size(x) ((sizeof(x) + sizeof(int) - 1) & ~(sizeof(int) - 1)) #define va_start_t(ap,last) (ap = (va_list)((char *)(&last) + __va_size(last))) #define va_arg_t(ap, type) (*(type *)((ap += __va_size(type)) - (__va_size(type)))) #define va_end_t(ap) ((void)0) #endif //コンパイラのものを利用する void test1(int count,...){ va_list args; int i; va_start(args,count); for(i=0;i<count;i++){ printf("%2d:%d\n",i,va_arg(args,int)); } va_end(args); } //自分で作ったものを利用する void test2(int count,...){ va_list_t args; int i; va_start_t(args,count); for(i=0;i<count;i++){ printf("%2d:%d\n",i,va_arg_t(args,int)); } va_end_t(args); } int main(){ test1(10,1,2,3,4,5,6,7,8,9,10); test2(10,1,2,3,4,5,6,7,8,9,10); return 0; }