inline識別子と__inline識別子はコンパイラに関数が呼ばれるそれぞれの場所に関数のコピーを挿入する(関数のインライン展開)ように指示します。
inline function_declarator; __inline function_declarator; // Microsoft Specific __forceinline function_declarator; // Microsoft Specific
挿入(インライン展開)はコンパイラの評価の結果有利だと判断された場合に限り発生します。インライン展開は関数コールにともなうオーバヘッドを軽減すると同時にコードサイズを大きくします。forceinlineキーワードはコンパイラではなくプログラマにインライン展開が有利かどうかの判断を委ねます(このキーワードを使うと強制的にインライン展開する)。安易に__forceinlineを使うとコードが大きくなるばかりで、些細な効率しかもたらさないか、場合によっては依然効率は改善しないかもしれません(実行ファイルの巨大化によって)。インライン関数を使うと関数コールにともなうオーバヘッドが取り除かれるのでプログラムの実行速度を改善することができます。
__based |
__cdecl(C/C++のデフォルトの呼び出し規約のための修飾子) |
__declspec(記憶クラスの詳細な属性を指定) |
__fastcall |
__restrict |
__stdcall(__stdcall呼び出し規約のための修飾子) |
__w64 |
__unaligned |
これはCとC++のデフォルトの呼び出し規約です。スタックは呼び出し側でクリーンアップされるので、可変長引数を持つ関数をそのまま呼び出すことができます。__stdcallは呼ばれる側がスタックをクリーンアップしますので、可変長引数を持つ関数には使えません。以下にこの呼び出し規約の内容を示します。
引数の渡される順番 | 右から左 |
---|---|
スタック操作引数の渡される順番 | 呼び出し側が(関数コール後)引数に使ったスタックをポップする |
名前修飾規約 | Cのリンクを用いる__cdecl関数を除いて、名前の先頭にプリフィクス文字'_'が付加される |
Case翻訳規約 | case翻訳されない |
Itaniumプロセッサファミリ(IPF)とx64プロセッサでは、__cdeclはコンパイラによって受け入れられますが無視されます(これはIPFの場合、呼び出し規約で引数がレジスタ渡しされるためです)。 cdecl修飾子は変数または関数名の前に置きます。Cの名前規約と呼び出し規約がデフォルトなので/Gz(stdcall)または/Gr(fastcall)コンパイラオプションを指定するときだけ、__cdecl を用います。/Gdコンパイラオプションを使うと強制的に__cdecl呼び出し規約が適用されます。
ANSI仕様のC, C++では記憶クラスとして、staicやexternキーワードが用意されていますが、これ以外の記憶クラスを指定することができません。Visual Studioでは__declspecキーワードを使って、さらに詳細な記憶クラスの属性を指定することができます。たとえば、threadを指定するとスレッドローカルストレージを指定することができます。
__declspec ( extended-decl-modifier-seq )
__stdcall呼び出し規約はWin32 API関数の呼び出しに用いられます。この規約を使う関数の呼び出しでは、呼び出し側はスタックをクリアし、コンパイラは可変長引数を持つ関数に_cdeclを使います。この呼び出し規約を使う関数は関数のプロトタイプを必要とします。
ライブラリの仕様を調べると、特殊な表記(注釈, annotations)が見つかることがあります。たとえば、次のような表記です。
_In_z and _Out_z_cap_(_Size)
これらの表記はSAL(Microsoft source-code annotation language)による記述です。SALは関数がパラメータを使う方法を説明する注釈(annotations )のセットを提供します。このような表記はヘッダ注釈(Header annotations)またはSAL注釈(SAL annotations)と呼ばれます。 msdnではヘッダ注釈とSAL注釈が別々に説明されているので混乱しますが、両者は同じことを意味しているようです。 以下では「ヘッダ注釈」という呼び方に統一します。
ヘッダ注釈は関数の型の前、または関数値の前に置くことができ、パラメータや関数値に関する関数の振る舞いを説明するために用いられます。これらの注釈はAPIが正しくコールされるようにWindowsの多くのヘッダファイルで追加されています。コード解析(code analysis)の機能(Visual Studio 2005で追加された)を使うと、コンパイラはヘッダ注釈で指定された方法に従わない関数コールに対してレベル6000のワーニングを生成します。 ヘッダ注釈はユーザーのプログラムでも利用することができます。ヘッダ注釈はSpecstrings.h内で定義され、Standard Annotation Language (SAL)の一部で組み込みプリミティブとして以下を使って実装されます。
_declspec("SAL_*")
注釈にはバッファ注釈(buffer annotations)とアドバンスド注釈(advanced annotations)の2つのクラスがあります。
バッファ注釈は関数がポインタをどのように使うかを説明しバッファオーバーランを検出できるようにします。そ れぞれのパラメータはゼロまたは1つのバッファ注釈を使うことができます。 バッファ注釈は先頭のアンダースコアと以下で説明するコンポーネントによって構成されます。それぞれのパラメータには、1つのバッファ注釈のみ使用できます。
分類 | オプション | 説明 |
---|---|---|
Indirection | パラメータまたは戻り値pとバッファポインタとの間接レベルを示します。 | |
none | pがバッファポインタ。 | |
_deref | *pがバッファポインタ。pはNULL以外の値である必要があります。 | |
_deref_opt | *pはバッファポインタである可能性があります。pにはNULLを指定することができます。この場合、残りの注釈は無視されます。 | |
Direction | 関数が(入出力に関して)バッファをどのように使用するかを示します。 | |
none | パラメータに対してこのカテゴリの注釈が用いられない場合、このバッファはアクセスされません。 戻り値に対して用いられこのカテゴリの注釈が用いられない場合、または _derefが用いられてこのカテゴリの注釈が用いられない場合、関数がバッファを提供し、終了時に初期化前の状態に戻します。 上記以外の場合、呼び出し元がバッファを提供します(alloc 関数と free 関数に対してのみ使用可能)。 |
|
_in | 関数はこのバッファに対して読み込みのみを行います。呼び出し側がバッファを提供し初期化する必要があります。この注釈を_deref と一緒に使用することはできません。 | |
_inout | 関数はこのバッファに対して読み込みと書き込みの両方を行うことができます。呼び出し側がバッファを提供し初期化する必要があります。_deref と一緒に使用する場合、バッファは関数によってリロケートされるかも知れません。 | |
_out | 関数はこのバッファへに対しての書き込みのみを行います。 戻り値に対してこの注釈を用いる場合、または _deref と共に用いる場合、関数がバッファを提供し、終了時に初期化前の状態に戻します。 上記以外の場合、呼び出し側がバッファを提供し、関数がこれを初期化します。 |
|
Buffer size units | バッファの合計(アクセス可能な)サイズの単位を示します | |
none | このバッファサイズは指定されません。型がバッファサイズを指定する場合 (LPSTR、LPWSTR など)、サイズは型によって指定されます。それ以外の型ではバッファのサイズは1要素分のサイズになります。_in, _out, _inoutのいずれかと一緒に用いる必要があります。 | |
_bcount | バッファ サイズは明示的なバイト数 | |
_ecount | バッファ サイズは明示的な要素数 | |
Buffer size | バッファのサイズを指定します。 | |
none | バッファのサイズは明示的に指定されません。この場合、_ecount も _bcount も使用されません。 | |
(size) | バッファの合計サイズのみを指定します。_ecountや_bcountと一緒に用いられ、_part とは一緒に用いられません。 | |
(size,length) | バッファの合計サイズsizeと初期済みのサイズ(length)を指定します。_ecount_partや _bcount_partと一緒に用いられます。 | |
Initialization | 関数によるバッファの初期化に関する振る舞いを指定します。 | |
none | 注釈ではなく型によって初期化レベルを指定します。たとえば、LPWSTR を初期化する関数は、文字列はNULLで終端される必要があります。 | |
_full | 関数は出力バッファ全体を初期化します。出力バッファでのみ用いられます。 | |
_part | 関数は出力バッファの一部を初期化し、初期化したサイズを明示します。出力バッファでのみ用いられます。 | |
Null-termination | バッファがNULLで終端されるかどうかを指定します。 | |
_z | バッファの終端はNULLによって示されます | |
_nz | NULLはバッファの終端を表しません(バッファはNULLで終わらない場合があります)。 | |
Optional | このバッファが省略可能であるかどうかを示します。 | |
none | このバッファへのポインタはNULL以外の値である必要があります(省略不可)。 | |
_opt | このバッファへのポインタはNULLを指定することで省略することができます。 |
GetModuleFileName関数の仕様書でのバッファ注釈の例で、hModuleはオプショナルな入力パラメータ、lpFilenameは出力パラメータ、nSizeパラメータは入力パラメータとして定義されています。
以下はSpecstrings.hで定義されている注釈(annotations )です。これらの意味を解析するには上記のテーブルの情報を参照してください。
__bcount(size) __bcount_opt(size) __deref_bcount(size) __deref_bcount_opt(size) __deref_ecount(size) __deref_ecount_opt(size) __deref_in __deref_in_bcount(size) __deref_in_bcount_opt(size) __deref_in_ecount(size) __deref_in_ecount_opt(size) __deref_in_opt __deref_inout __deref_inout_bcount(size) __deref_inout_bcount_full(size) __deref_inout_bcount_full_opt(size) __deref_inout_bcount_opt(size) __deref_inout_bcount_part(size,length) __deref_inout_bcount_part_opt(size,length) __deref_inout_ecount(size) __deref_inout_ecount_full(size) __deref_inout_ecount_full_opt(size) __deref_inout_ecount_opt(size) __deref_inout_ecount_part(size,length) __deref_inout_ecount_part_opt(size,length) __deref_inout_opt __deref_opt_bcount(size) __deref_opt_bcount_opt(size) __deref_opt_ecount(size) __deref_opt_ecount_opt(size) __deref_opt_in __deref_opt_in_bcount(size) __deref_opt_in_bcount_opt(size) __deref_opt_in_ecount(size) __deref_opt_in_ecount_opt(size) __deref_opt_in_opt __deref_opt_inout __deref_opt_inout_bcount(size) __deref_opt_inout_bcount_full(size) __deref_opt_inout_bcount_full_opt(size) __deref_opt_inout_bcount_opt(size) __deref_opt_inout_bcount_part(size,length) __deref_opt_inout_bcount_part_opt(size,length) __deref_opt_inout_ecount(size) __deref_opt_inout_ecount_full(size) __deref_opt_inout_ecount_full_opt(size) __deref_opt_inout_ecount_opt(size) __deref_opt_inout_ecount_part(size,length) __deref_opt_inout_ecount_part_opt(size,length) __deref_opt_inout_opt __deref_opt_out __deref_opt_out_bcount(size) __deref_opt_out_bcount_full(size) __deref_opt_out_bcount_full_opt(size) __deref_opt_out_bcount_opt(size) __deref_opt_out_bcount_part(size,length) __deref_opt_out_bcount_part_opt(size,length) __deref_opt_out_ecount(size) __deref_opt_out_ecount_full(size) __deref_opt_out_ecount_full_opt(size) __deref_opt_out_ecount_opt(size) __deref_opt_out_ecount_part(size,length) __deref_opt_out_ecount_part_opt(size,length) __deref_opt_out_opt __deref_out __deref_out_bcount(size) __deref_out_bcount_full(size) __deref_out_bcount_full_opt(size) __deref_out_bcount_opt(size) __deref_out_bcount_part(size,length) __deref_out_bcount_part_opt(size,length) __deref_out_ecount(size) __deref_out_ecount_full(size) __deref_out_ecount_full_opt(size) __deref_out_ecount_opt(size) __deref_out_ecount_part(size,length) __deref_out_ecount_part_opt(size,length) __deref_out_opt __ecount(size) __ecount_opt(size) __in __in_bcount(size) __in_bcount_opt(size) __in_ecount(size) __in_ecount_opt(size) __in_opt __inout __inout_bcount(size) __inout_bcount_full(size) __inout_bcount_full_opt(size) __inout_bcount_opt(size) __inout_bcount_part(size,length) __inout_bcount_part_opt(size,length) __inout_ecount(size) __inout_ecount_full(size) __inout_ecount_full_opt(size) __inout_ecount_opt(size) __inout_ecount_part(size,length) __inout_ecount_part_opt(size,length) __inout_opt __out __out_bcount(size) __out_bcount_full(size) __out_bcount_full_opt(size) __out_bcount_opt(size) __out_bcount_part(size,length) __out_bcount_part_opt(size,length) __out_ecount(size) __out_ecount_full(size) __out_ecount_full_opt(size) __out_ecount_opt(size) __out_ecount_part(size,length) __out_ecount_part_opt(size,length) __out_opt
アドバンスド注釈(Advanced annotations)(msdnでは「詳細な注釈」と訳されています)はパラメータや戻り値に関する追加的な情報を提供します。それぞれのパラメータや戻り値はゼロまたは1つのアドバンスド注釈を使います。
Annotation | Description |
---|---|
__blocksOn(resource) | 指定されたリソースのファンクションブロック(functions blocks) |
__callback | 関数のポインタとして使うことのできる関数(コールバック関数を表現するために用いられると思われます) |
__checkReturn | 呼び出し側は戻り値をチェックしなければなりません |
__format_string | printfスタイルの %マーカーを持つパラメータ |
__in_awcount(expr,size) | exit時にexprが真の場合、入力バッファのサイズがバイト数で示されます。exprが偽の場合サイズは要素数で示されます。 |
__nullnullterminated | 2つのNULLで終端されたバッファ。 |
__nullterminated | NULLで終端されたバッファ。 |
__out_awcount(expr, size) | exit時点でexprが真の場合、出力バッファのサイズはバイト数で示され、偽の場合要素すうで示されます。 |
__override | 仮想メソッドのためにC#スタイルのオーバライドの振る舞いを指定します。 |
__reserved | このパラメータが将来の利用に備えてreservedであることを示します。このパラメータはNULLまたはゼロでなければなりません。 |
__success(expr) | exit時点でexprが真の場合、呼び出し側は別の注釈によって指定を信頼することができ、偽の場合信頼することができません。この注釈はHRESULT値を返す関数に自動的に追加されます。 |
__typefix(ctype) | パラメータを宣言されたタイプではなく、指定されたタイプとして扱います。 |
C言語では(通常は)main関数がプログラムのエントリポイントとなりますが、 システムによってmain関数が呼ばれるまで(とmain関数の後始末)は「ランタイムライブラリ」と呼ばれるライブラリによって暗黙のうちに処理されることが多いです。Visual Studioでも多様なランタイムライブラリが提供されますが、これらのライブラリが「ランタイム化」によって何を実現しているのか、msdnのドキュメントではあまり体系的には述べられていないようです。
Cランタイム(CRT)ライブラリは次の条件の違いによるいくつかのバージョンがあります。
現在は、すべてのCRTライブラリがマルチスレッドに対応しています。