C および C++ の Microsoft 拡張機能

Microsoft Visual C++ (MSVC) は、この記事で詳しく説明するように、C および C++ 言語標準をいくつかの方法で拡張します。

MSVC C++ コンパイラは、ISO C++17 の一部の機能と一部の Microsoft 固有言語拡張機能を備えた ISO C++14 を既定でサポートしています。 サポートされている機能の詳細については、「Visual Studio バージョン別の Microsoft C/C++ 言語準拠」を参照してください。 /std コンパイラ オプションを使用して、ISO C++17 および ISO C++20 言語機能の完全なサポートを有効にすることができます。 詳細については、「/std (言語標準バージョンの指定)」を参照してください。

指定されている場合、/Za コンパイラ オプションを使用して、一部の MSVC C++ 言語拡張機能を無効にすることができます。 Visual Studio 2017 以降のバージョンでは、/permissive- コンパイラ オプションにより、Microsoft 固有の C++ 言語拡張機能が無効になります。 /std:c++20 および /std:c++latest コンパイラ オプションによって、/permissive- コンパイラ オプションは暗黙的に有効になります。

既定では、MSVC がコードを C としてコンパイルするときに、Microsoft 固有の言語拡張機能を使用して ANSI C89 を実装します。 これらの MSVC 拡張機能の一部は、ISO C99 以降で標準化されています。 ほとんどの MSVC C 拡張機能は、この記事で後述するように、/Za コンパイラ オプションを使用して無効にすることができます。 /std コンパイラ オプションを使用して、ISO C11 と C17 のサポートを有効にすることができます。 詳細については、「/std (言語標準バージョンの指定)」を参照してください。

標準の C ランタイム ライブラリは、Windows のユニバーサル C ランタイム ライブラリ (UCRT) によって実装されます。 UCRT では、多くの POSIX および Microsoft 固有のライブラリ拡張機能も実装されています。 UCRT では、実装固有の特定の注意事項がある ISO C11 と C17 C ランタイム ライブラリ標準をサポートしています。 完全な ISO C99 標準 C ランタイム ライブラリはサポートされていません。 詳細については、ユニバーサル C ランタイム ライブラリのドキュメントの「互換性」を参照してください。

キーワード

MSVC では、C および C++ に Microsoft 固有のキーワードがいくつか追加されます。 キーワードの一覧で、先頭に 2 つのアンダースコアがあるキーワードは MSVC の拡張機能です。

キャスト

C++ コンパイラおよび C コンパイラでは、次の種類の非標準キャストをサポートしています。

  • C コンパイラでは、非標準キャストをサポートして左辺値を生成します。 次に例を示します。

    char *p;
    (( int * ) p )++;
    // In C with /W4, both by default and under /Ze:
    //     warning C4213: nonstandard extension used: cast on l-value
    // Under /TP or /Za:
    //     error C2105: '++' needs l-value
    

    Note

    この拡張機能は、C 言語でのみ使用できます。 C++ コードで次の C 標準形式を使用して、ポインターを別の型へのポインターであるかのように変更できます。

    この例を次のように書き換えると、C 規格に準拠します。

    p = ( char * )(( int * )p + 1 );
    
  • C と C++ の両方のコンパイラで、データ ポインターへの関数ポインターの非標準キャストがサポートされています。 次に例を示します。

    int ( * pfunc ) ();
    int *pdata;
    pdata = ( int * ) pfunc;
    /* No diagnostic at any level, whether compiled with default options or under /Za */
    

可変長の引数リスト

C および C++ の両方のコンパイラでは、可変数の引数を指定する関数宣言子を使用できます。その後ろには、型を指定する関数定義を記述します。

void myfunc( int x, ... );
void myfunc( int x, char * c )
{ }
// In C with /W4, either by default or under /Ze:
//     warning C4212: nonstandard extension used: function declaration used ellipsis
// In C with /W4, under /Za:
//     warning C4028: formal parameter 2 different from declaration
// In C++, no diagnostic by default or under /Za.

単一行コメント

C コンパイラでは、次のように 2 つのスラッシュ (//) で始まる単一行コメントがサポートされています。

// This is a single-line comment.

単一行コメントは C99 の機能です。 これらは /Za による影響を受けず、どのレベルでも診断が発生しません。

Scope

C コンパイラでは、次のようなスコープ関連のコードを記述できます。

  • externstatic として再定義する。

    extern int clip();
    static int clip() {}
    // In C and C++ with /W4, either by default or under /Ze:
    //     warning C4211: nonstandard extension used: redefined extern to static
    // In C and C++ under /Za:
    //     error C2375: 'clip': redefinition; different linkage
    
  • 同じスコープ内で typedef 定義を複数回記述する。

    typedef int INT;
    typedef int INT; // No diagnostic at any level in C or C++
    
  • 関数宣言子をファイル スコープにする。

    void func1()
    {
         extern double func2( double );
         // In C at /W4:  warning C4210: nonstandard extension used: function given file scope
    }
    int main( void )
    {
         func2( 4 );    //  /Ze passes 4 as type double
    }                  //  /Za passes 4 as type int
    
  • 非定数式で初期化したブロック スコープ変数を使用する。

    int clip( int );
    int bar( int );
    int main( void )
    {
         int array[2] = { clip( 2 ), bar( 4 ) };
    }
    int clip( int x )
    {
         return x;
    }
    int bar( int x )
    {
         return x;
    }
    

データの宣言と定義

C コンパイラでは、以下のデータ宣言およびデータ定義の機能をサポートしています。

  • 初期化子内に文字定数と文字列定数を混在させる。

    char arr[6] = {'a', 'b', "cde"};
    // In C with /W4, either by default or under /Ze:
    //     warning C4207: nonstandard extension used: extended initializer form
    // Under /Za:
    //     error C2078: too many initializers
    
  • ビット フィールドを unsigned intsigned int 以外のベース型で指定する。

  • 型がない宣言子:

    x;
    // By default or under /Ze, /Za, /std:c11, and /std:c17, when /W4 is specified:
    //     warning C4431: missing type specifier - int assumed. Note: C no longer supports default-int
    //     warning C4218: nonstandard extension used: must specify at least a storage class or a type
    */
    int main( void )
    {
         x = 1;
    }
    
  • 可変長配列を構造体および共用体の最後のフィールドとして指定する。

    struct zero
    {
         char *c;
         int zarray[];
         // In C with /W4, either by default, under /Ze, /std:c11, and /std:c17:
         //     warning C4200: nonstandard extension used: zero-sized array in struct/union
         // Under /Za:
         //     error C2133: 'zarray': unknown size
    };
    
  • 名前のない (無名) 構造体を使用する。

    struct
    {
         int i;
         char *s;
    };
    // By default or under /Ze, /std:c11, and /std:c17, when /W4 is specified:
    //     warning C4094: untagged 'struct' declared no symbols
    // Under /Za:
    //     error C2059: syntax error: 'empty declaration'
    
  • 名前のない (無名) 共用体を使用する。

    union
    {
         int i;
         float fl;
    };
    // By default or under /Ze, /std:c11, and /std:c17, when /W4 is specified:
    //     warning C4094: untagged 'union' declared no symbols
    // Under /Za:
    //     error C2059: syntax error: 'empty declaration'
    

浮動小数点組み込み型の関数

x86 の C++ コンパイラと C コンパイラのどちらでも、/Oi を指定すると、atanatan2cosexploglog10sinsqrttan 関数のインライン生成がサポートされます。 これらの組み込みは errno 変数を設定しないため、標準に準拠していません。

ISO646.H無効

/Ze で次の演算子の表示形式を使用する場合は、iso646.h をインクルードする必要があります。

Operator テキスト形式
&& and
&= and_eq
& bitand
| bitor
~ compl
! not
!= not_eq
|| or
|= or_eq
^ xor
^= xor_eq

これらのテキスト形式は、/Za で、または /permissive- が明示的または暗黙的に指定されている場合は、C++ のキーワードとして使用できます。

関連項目

/Za/Ze (言語拡張機能を無効にする)
MSVC コンパイラ オプション
MSVC コンパイラのコマンド ライン構文