はじめに
今回は、C,C++などで使用できる可変個引数の関数の作成をしていきます!
多分、C,C++などの言語を触ったことが少しでもある人は、
printf関数みたいな関数を自分で作れないかなぁと思った事がある方も多いはずです。
自分のメモ帳が半分なのでほとんどわからん!って人がいたらごめんなさい( ;∀;)
ある程度、わかりやすいようになるまでは更新していきたいと思っています。
※VisualStudio2017を使用しています
可変個引数の関数の作成
stdarg.hのマクロなどの説明
/---va_start---/
関数の定義:va_start(/va_list型変数名/, /関数の右から2番目の引数名/);
va_list型の変数を初期化する関数マクロ
/---va_end---/
関数の定義:va_end(/va_list型変数/);
va_startマクロ・va_copyマクロにて初期化が行われたva_list型変数を関数が終了する時に、
初期化が行われた数だけva_endマクロで正常な状態に復帰させる必要がある。
/---va_list---/
宣言:va_list 変数名
va_list型変数を宣言する時に使用する型名
元のデータ型はchar*型
/---va_arg---/
関数の定義:va_arg(/値を取り出したいva_list型の変数/, 値を取り出したいデータ型);
可変個実引数を返す関数マクロ
va_argマクロは使用するごとに、可変個引数の参照個所が一つずつ後ろにずれていく性質がある。
ただし、データ型を正しく指定できなければエラーとなるので正しいデータ型指定する必要がある。
例)
printf("%d%f", int型変数i, float型変数f); //だった場合は
va_arg(va_list型変数, int);//一度目の呼び出しなので一番最初のint型変数iを参照している
va_arg(va_list型変数, float);//参照個所が後ろにずれているのでfloat型変数fを参照している
/---va_copy---/
関数の定義:va_copy(/*コピー先va_list型変数*/,/*コピー元va_list型変数*/);
va_list型変数のコピーを作成する関数マクロ。
コピー元・コピー先の最低二つのva_list型変数を作成しておく必要がある。
また、コピー元のva_list型変数をコピー前にva_startマクロで初期化しておく必要がある。
関数定義部
1.stdarg.hをインクルードする ※windows.hを使用する場合にはインクルードをしなくても動きます。
2.関数の引数として、可変個引数が使用できるものにすること(printf関数ならconst char*型)
3.関数の引数に、可変個引数を使用すること
可変個引数は、...と記述するまた、可変個引数は関数の一番右側でなければいけない。
関数内部
1.va_list型を変数を宣言・使用する
2.va_startマクロを使用し、va_list型の変数の使用を開始する //可変個引数の使用を開始する
3.va_endマクロを使用し、va_list型の変数の使用を終了する //可変個引数の使用を終了
・引数を複数回使用したい場合はva_startマクロ・va_copyマクロを使用する
・va_startマクロ・va_copyマクロを使用して初期化されたva_list型変数の数だけva_endマクロを使用して終了を宣言する
※1~3は可変個引数の関数を作成する場合、絶対に使用すること!
関数の引数として可変個引数を使用する場合は、...(ドット3つ)を使用する。
# include<stdarg.h>
void print(const char* text, .../*可変個引数*/){
char text_array[200];
va_list args;//va_listマクロを使用
va_start( args, text );
vsprintf_s( text_array, text, args );//vsprintfを使用する場合は #define _CRT_SECURE_WARNINGS
va_end( args );
}
int main(){
int loopCounter = 0;
while(true){
print("ループ回数 : %d", loopCounter);
loopCounter += 1;
}
}
可変個引数マクロ
1.関数マクロの引数として_VA_ARGS_を使用する ※_VA_ARGS_は通常の関数の引数には使用できません
# define PRINT(...) printf(_VA_ARGS_);
int main(){
int x = 0;
PRINT("%d", x);
}
終わりに
こんな感じで可変個引数を使用した関数は作れます。
ちなみに、少し関数の引数や内部構造をいじれば他の関数に作り替えることも可能です。←当たり前の事言ってますねw
座標軸指定が必要なら関数の引数として座標を入れてみたりとか...
もしよければ、関数の引数を変更して遊んでみると意外とわかることが増えるかも...
あと、今回ファイル分けしているものに関してはこのままでは、動きません。
ごめんなさいm(__)m
ファイル分けはいろいろなサイトに行けば書いてあるので今回は省きます。