Microsoft C 和 C++ 扩展

Visual C++ 如下扩展 ANSI C 和 ANSI C++ 标准。

关键字

多个关键字添加到中。 在 C++关键字的列表,具有的关键字两个前导下划线是 Visual C++ 扩展。

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

根据该条件 (/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;

强制转换

编译器支持这些非 ANSI 转换:

  • 非 ANSI 导致左值的转换。 例如:

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

    备注

    此扩展可在仅限于 C 语言。在 C++ 代码中使用下列 ANSI C 标准窗体修改指针,就象它指向不同的类型。

    前面的示例看复盖符合 ANSI C 标准。

    p = ( char * )(( int * )p + 1 );
    
  • 非 ANSI 函数指针的转换为数据的指针。 例如:

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

    在转换到数据指针之前,若要执行相同的转换并维护 ANSI 兼容性,您可以将函数指针到 uintptr_t :

    pdata = ( int * ) (uintptr_t) 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 [],不是常数字符 (*) []

下面的示例在 /Za 下输出 char const (*)[4],但在 /Ze 下输出 char const [4]。

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

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

请参见

参考

/Za、/Ze(禁用语言扩展)

编译器选项

设置编译器选项