Microsoft C 和 C++ 扩展

更新:2007 年 11 月

以下是对 ANSI C 和 ANSI C++ 标准的 Visual C++ 扩展:

关键字

Microsoft 用数个附加关键字扩展 C++ 语言。有关完整列表,请参见“C++ 语言参考”中的 C++ Keywords。有两个前导下划线的关键字是 Microsoft 扩展。

static const 整型(或枚举)成员的类外定义

在标准 (/Za) 下,需要为数据成员做出类外定义。例如,

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

/Ze 下,类外定义对于静态、常量整型和常量枚举数据成员是可选的。只有为 static 且为 const 的整型和枚举可以在类内有初始值设定项;初始化表达式必须是常数表达式。

若要在提供类外定义时(当在头文件中提供类外定义,且该头文件包含在多个源文件中时)避免错误,应使用 selectany。例如:

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

强制转换

编译器支持下列两种非 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 编译器支持单行注释,它是用两个正斜杠 (//) 字符引入的:

// 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 Specific >END x86 Specificatanatan2cosexploglog10sinsqrttan 函数。对于 C,当使用这些内部函数时会丢失 ANSI 一致性,因为它们没有设置 errno 变量。

将非常数指针参数传递给需要常数指针参数的引用的函数

这是对 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_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(禁用语言扩展)

编译器选项

设置编译器选项