C言語の中の変長パラメータ
2795 ワード
私たちはC言語プログラミングにおいて、いくつかのパラメータの個数可変の関数、例えばprintf()に出会います.この関数の定義はこうです.
このような長いパラメータの関数を実現するには、データ構造va_を使用する必要があります.リストとマクロヴァ_スタートアル、ヴァグend、これらはstdarg.hで定義されたマクロです.
va_リストは、保存関数パラメータを定義したデータ構造である.
va_startマクロはva_を初期化します.list変数の最初のパラメータはva_です.リストオブジェクトは、2番目のパラメータが可変パラメータの前のパラメータであり、固定パラメータです.
初期化が完了しました.list変数を使用すると、va_を使用できます.argマクロ
va_argマクロは後の可変パラメータを得るために使用されます.その最初のパラメータはva_です.リストオブジェクト、2番目のパラメータは戻りパラメータの種類です.
va_endマクロは変数の取得を終了し、そのポインタを変数0にセットします.
次はva_ですリストの具体的な実現(vc 2003):
int printf( const char* format, ...);
しかし、長いパラメータの関数はどうやって実現されますか?このような長いパラメータの関数を実現するには、データ構造va_を使用する必要があります.リストとマクロヴァ_スタートアル、ヴァグend、これらはstdarg.hで定義されたマクロです.
va_リストは、保存関数パラメータを定義したデータ構造である.
va_startマクロはva_を初期化します.list変数の最初のパラメータはva_です.リストオブジェクトは、2番目のパラメータが可変パラメータの前のパラメータであり、固定パラメータです.
初期化が完了しました.list変数を使用すると、va_を使用できます.argマクロ
va_argマクロは後の可変パラメータを得るために使用されます.その最初のパラメータはva_です.リストオブジェクト、2番目のパラメータは戻りパラメータの種類です.
va_endマクロは変数の取得を終了し、そのポインタを変数0にセットします.
次はva_ですリストの具体的な実現(vc 2003):
#ifdef _M_ALPHA
typedef struct {
char *a0; /* pointer to first homed integer argument */
int offset; /* byte offset of next parameter */
} va_list;
#else
typedef char * va_list;
#endif
va_が見られますlistは実際にマシンタイプに関するマクロであり、alphaマシンを除いて、他のマシンタイプはcharタイプのポインタ変数と定義されています.char*と定義されているのは、その変数をアドレス毎に、つまりバイト毎にパラメータを巡回できるからです.マクロの実現は以下の通りで、内容が分かりやすいので、紹介しません.#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
#ifdef __cplusplus
#define _ADDRESSOF(v) ( &reinterpret_cast<const char &>(v) )
#else
#define _ADDRESSOF(v) ( &(v) )
#endif
参考コードは以下の通りです.#include <stdio.h>
#include <stdarg.h>
#include <string.h>
void test(char src[], ...);
int main()
{
char str[] = "content";
test("this is %d %s %c", 123, str, 'p');
return 0;
}
void test(char src[], ...)
{
int num=1;
va_list args;
va_start(args, src);
int i = 1;
int len = strlen(src);
while(i<len)
{
if(src[i-1] == '%')
{
switch(src[i])
{
case 'd':
{
int p = va_arg(args, int);
printf("%d args : %d
", num++, p);
break;
}
case 'c':
{
// ,va_arg
int ch = va_arg(args, int);
printf("%d args : %c
", num++, (char)ch);
break;
}
case 's':
{
char * pStr = va_arg(args, char *);
printf("%d args : %s
", num++, pStr);
break;
}
}
}
i++;
}
va_end(args);
}