Microsoft C/C++ の拡張機能

更新 : 2007 年 11 月

ANSI C および ANSI C++ 規格に対する Visual C++ の拡張機能を以下に示します。

キーワード

Microsoft C++ の言語拡張機能では、いくつかの追加のキーワードを使用しています。完全な一覧については、『C++ Language Reference』の「C++ Keywords」を参照してください。先頭にアンダースコアが 2 つ付いているキーワードは、Microsoft の拡張機能です。

静的な定数型の整数 (または列挙) メンバのクラス外定義

標準 (/Za) では、データ メンバのクラス外定義が必要です。この例を次に示します。

class CMyClass  {
   static const int max = 5;
   int m_array[max];
}
...
const int CMyClass::max;   // out of class definition

/Ze では、静的で定数型の整数および列挙のデータ メンバのクラス外定義は省略可能です。クラス内に初期化子を持つことができるのは、静的で定数型の整数と列挙だけです。初期化式には、定数型の式を使用する必要があります。

クラス外定義を指定する場合は (クラス外定義がヘッダー ファイルに指定され、そのヘッダー ファイルを複数のソース ファイルでインクルードする場合)、エラーを防ぐために selectany を使用する必要があります。たとえば、次のようにします。

__declspec(selectany) const int CMyClass::max = 5;

キャスト

コンパイラは、次の 2 とおりの非 ANSI キャストをサポートします。

  • 左辺値を生成するための非 ANSI キャスト

    char *p;
    (( int * ) p )++;
    

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

    p = ( char * )(( int * )p + 1 );
    
  • 関数ポインタからデータ ポインタへの非 ANSI キャスト

    int ( * pfunc ) (); 
    int *pdata;
    pdata = ( int * ) pfunc;
    

    上の例と同じキャストを行い、ANSI 規格に準拠させるには、次に示すように関数ポインタをまず int 型にキャストし、その後データ ポインタにキャストします。

    pdata = ( int * ) (int) pfunc;
    

可変長の引数リスト

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

void myfunc( int x, ... );
void myfunc( int x, char * c )
{ }

単一行コメント

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

// This is a single-line comment.

スコープ

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

  • extern を static として再定義する。

    extern int clip();
    static int clip()
    {}
    
  • 同じスコープ内で typedef 定義を複数回記述する。

    typedef int INT;
    typedef int INT;
    
  • 関数宣言子をファイル スコープにする。

    void func1()
    {
        extern int func2( double );
    }
    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[5] = {'a', 'b', "cde"};
    
  • ビット フィールドを unsigned intsigned int 以外のベース型で指定する。

  • ストレージ クラスもデータ型も指定せずに宣言子を使用する。

    x;
    int main( void )
    {
        x = 1;
    }
    
  • 可変長配列を構造体および共用体の最後のフィールドとして指定する。

    struct zero
    {
        char *c;
        int zarray[];
    };
    
  • 名前のない (無名) 構造体を使用する。

    struct
    {
        int i;
        char *s;
    };
    
  • 名前のない (無名) 共用体を使用する。

    union
    {
        int i;
        float fl;
    };
    
  • 名前のないメンバを使用する。

    struct s
    {
       unsigned int flag : 1;
       unsigned int : 31;
    }
    

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

コンパイラは、/Oi が指定されている場合に、x86 固有の仕様→atanatan2cosexploglog10sinsqrt、および tan の各関数の← x86 固有の仕様インライン生成をサポートします。これらの関数のインライン形式では errno 変数が設定されないため、C プログラムでは ANSI C に準拠しなくなります。

const ポインタ パラメータの参照を予測している関数に非 const ポインタ パラメータを渡す

これは C++ の拡張機能です。次のコードを /Ze でコンパイルします。

typedef   int   T;

const T  acT = 9;      // A constant of type 'T'
const T* pcT = &acT;   // A pointer to a constant of type 'T'

void func2 ( const T*& rpcT )   // A reference to a pointer to a constant of type 'T'
{
   rpcT = pcT;
}

T*   pT;               // A pointer to a 'T'

void func ()
{
   func2 ( pT );      // Should be an error, but isn't detected
   *pT   = 7;         // Invalidly overwrites the constant 'acT'
}

ISO646.H が有効でない

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

  • && (and)

  • &= (and_eq)

  • & (bitand)

  • | (bitor)

  • ~ (compl)

  • ! (not)

  • != (not_eq)

  • || (or)

  • |= (or_eq)

  • ^ (xor)

  • ^= (xor_eq)

リテラル文字列のアドレスの型が const char (*) [] ではなく const char [] である

/Za で char const (*)[4] を出力し、/Ze で char const [4] を出力する例を次に示します。

#include <stdio.h>
#include <typeinfo>

int main()
{
    printf_s("%s\n", typeid(&"abc").name());
}

参照

参照

/Za、/Ze (言語拡張機能の無効化)

コンパイラ オプション

コンパイラ オプションの設定