Categories: 未分類

stdarg.h

Stdarg.h

stdarg.hヘッダであるC標準ライブラリのCプログラミング言語機能が受け入れることを可能にする引数の不定数。数とタイプが不明な関数の引数のリストをステップスルーするための機能を提供します。C ++は、ヘッダーでこの機能を提供しますcstdarg。
の内容stdarg.hは通常、可変個引数関数で使用されますが、可変個引数関数vprintfによって呼び出される他の関数(たとえば)で使用される場合も

コンテンツ
1 可変個引数関数の宣言
2 可変個引数関数の定義
3 stdarg.hタイプ
4 stdarg.hマクロ
5 引数へのアクセス
5.1 名前のない引数を他の呼び出しに渡す
6 型安全性
7 例
8 varargs.h
9 参考文献

可変個引数関数の宣言
可変個引数関数は、可変数の引数を取ることができる関数であり、最後のパラメーターの代わりに省略記号を使用して宣言されます。このような関数の例はprintfです。典型的な宣言は
intチェック(int a 、double b 、…);
可変個引数関数には、少なくとも1つの名前付きパラメーターが必要です。たとえば、
char *間違っている(…);
Cでは許可されていません(C ++では、このような宣言は許可されています)。Cでは、省略記号の前にコンマを付ける必要がC ++では、これはオプションです。

可変個引数関数の定義
同じ構文が定義で使用されます。
long func (char 、double 、int 、…); long func (char a 、double b 、int c 、…)
{{ / * … * /}
省略記号は、古いスタイルの関数定義には表示されない場合が

stdarg.hタイプ
名前
説明
互換性 va_list 引数を繰り返すためのタイプ
C89

stdarg.hマクロ
名前
説明
互換性 va_start 引数の反復を開始します va_listC89 va_arg
引数を取得するC89 va_end
無料 va_listC89 va_copy
あるコンテンツva_listを別のコンテンツにコピーする
C99

引数へのアクセス
名前のない引数にアクセスするにva_listは、可変個引数関数で型の変数を宣言する必要が次に、マクロva_startは2つの引数で呼び出されます。1つva_list目は型で宣言された変数で、2つ目は関数の最後に名前が付けられたパラメーターの名前です。この後、va_argマクロを呼び出すたびに次の引数が生成されます。の最初の引数va_argはva_listで、2番目の引数は関数に渡される次の引数の型です。最後に、関数が戻る前にva_endマクロを呼び出す必要がありva_listます。(すべての引数を読み取る必要はありません。)
C99は、va_copyの状態を複製できる追加のマクロ、を提供しますva_list。マクロ呼び出しはにva_copy(va2, va1)コピーva1されva2ます。
関数に渡される名前のない引数の数またはタイプを決定するために定義されたメカニズムはありません。関数は、これを何らかの方法で認識または決定するために必要なだけであり、その手段はさまざまです。一般的な規則は次のとおりです。
引数の型を示す指定子が埋め込まれたprintforのscanfようなフォーマット文字列の使用。
センチネル値可変長引数の最後に。
可変個引数の数を示すcount引数。

名前のない引数を他の呼び出しに渡す
名前のない引数リストのサイズは一般に不明であるため(ほとんどのコンパイラで採用されている呼び出し規約ではva_list、受信関数内でポイントされる名前のない引数ブロックのサイズを決定できません)、信頼できる一般的な転送方法もありません。名前のない引数を別の可変個引数関数に。引数リストのサイズを間接的な方法で決定できる場合でも(たとえば、のフォーマット文字列を解析することによってfprintf())、動的に決定された引数の数を、数とサイズとして内部可変個引数呼び出しに渡すポータブルな方法はありません。このような呼び出しに渡される引数の数は、通常、コンパイル時に認識されている必要がこの制限は、可変個引数関数の代わりに可変個引数マクロを使用することである程度緩和できます。さらに、ほとんどの標準ライブラリプロシージャは、名前のない引数リスト自体ではなく、名前のない引数リスト(つまり、初期化された変数)への参照をv受け入れる接頭辞付きの代替バージョンを提供します。たとえば、は、実際の名前のない引数リストの代わりに期待する代替バージョンです。したがって、ユーザー定義の可変個引数関数は、を使用して変数を初期化し、それを適切な標準ライブラリ関数に渡すことができます。事実上、名前のない引数リストは、値ではなく参照によって渡されます。Cでは、名前のない引数リストを値で渡す信頼できる方法がないため、代わりに受け入れる同等の関数を提供せずに可変個引数API関数を提供することは、悪いプログラミング手法と見なされます。va_listvfprintf()fprintf()va_listva_listva_startva_list

型安全性
一部のC実装は、コンパイラがフォーマット文字列とセンチネルの適切な使用をチェックできるようにするC拡張機能を提供します。これらの拡張機能を除いて、コンパイラーは通常、渡された名前のない引数が関数が期待する型であるかどうかを確認したり、必要な型に変換したりすることはできません。したがって、タイプが一致しない場合は未定義の動作が発生するため、この点で正確性を確保するように注意する必要がたとえば、期待される型がint *、の場合、nullポインタを(int *)NULL。として渡す必要がちょうど書き込みNULLのいずれかのタイプの引数につながるintか、void *正しいか、どちらも。もう1つの考慮事項は、名前のない引数に適用されるデフォルトの引数プロモーションです。Afloatは自動的にに昇格しますdouble。同様に、より狭いタイプの引数はまたはintにプロモートされます。名前のない引数を受け取る関数は、プロモートされた型を予期する必要がintunsigned int
GCCには、渡された引数をチェックする拡張機能が
format(archetype, string-index, first-to-check)
format属性の関数が取ることを指定しprintf、scanf、strftimeまたはstrfmon型チェックを書式文字列に対してあるべきスタイルの引数。たとえば、宣言:
extern int my_printf (void * my_object 、const char * my_format 、…)
__attribute __ ((形式(printfの、2 、3 )))。
コンパイラは、呼び出しの引数をチェックmy_printfして、printfスタイル形式の文字列引数との整合性を確認しますmy_format。— 
「5.27C言語ファミリの拡張-関数の属性の宣言」。取り出さ2009-01-03に。


#include #include / *負の引数が表示されるまで、すべての引数を一度に1つずつ出力します。 すべての引数はint型であると見なされます* /void printargs (int arg1 、…) {{ va_list ap ; int i ; va_start (ap 、arg1 ); for (i = arg1 ; i > = 0 ; i = va_arg (ap 、int ))
printf (”%d” 、i ); va_end (ap ); putchar (’ n’ );}int main (void ) {{ printargs (5 、2 、14 、84 、97 、15 、-1 、48 、-1 )。
printargs (84 、51 、-1 、3 )。
printargs (-1 ); printargs (1 、-1 ); 0を返す; }
このプログラムは次の出力を生成します。
5 2 14 84 97 1584 511
関数内から他のvarargs関数(sprintfなど)を呼び出すには、関数のvar argバージョン(この例ではvsprintf)を使用する必要が
void MyPrintf (const char * format 、…) {{ va_list args ; charバッファ; va_start (args 、format ); vsnprintf (buffer 、sizeof buffer 、format 、args );
va_end (args ); FlushFunnyStream (バッファ);}

varargs.h
POSIXの古いバージョンはvarargs.h、Cの標準化以前からのものであり、と同様の機能を提供するレガシーヘッダーを定義しましたstdarg.h。このヘッダーは、ISOCにもPOSIXにも含まれSingle UNIX Specificationの2番目のバージョンで定義されているように、このファイルには、次stdarg.hの例外を除いて、C89のすべての機能が含まれています。
標準のCの新しいスタイルの定義では使用できません
指定された引数は省略できます(標準Cでは少なくとも1つの引数が必要です)
インターフェースも異なります。たとえばprintargs、代わりに次のように記述します。
#include #include / *「void」タイプはありません。暗黙のintリターンを使用します。* /printargs (arg1 、va_alist ) va_dcl / *ここにセミコロンはありません!* / {{ va_list ap ; int i ; va_start (ap ); for (i = arg1 ; i > = 0 ; i = va_arg (ap 、int ))
printf (”%d” 、i ); va_end (ap ); putchar (’ n’ ); 戻る;}
同じように呼ばれます。
varargs.h実装の仕組みのため、古いスタイルの関数定義が必要です。逆に、古いスタイルの関数定義をstdarg.h。と混在させることはできません。

参考文献
^ “IEEE Std1003.1 ” 。 stdarg.h ^ 「単一UNIX仕様」。 varargs.h

admin

Share
Published by
admin

Recent Posts

ストルジースコフ

St%C5%99%C3%AD%…

4週間 ago

ステンプナ

St%C4%99pna Stę…

4週間 ago

Stępiński

St%C4%99pi%C5%8…

4週間 ago

ステファニー・ギボー

St%C3%A9phanie_…

4週間 ago

ステファニー

St%C3%A9phanie …

4週間 ago