Microsoft Extensions to C and C++
Collapse the table of content
Expand the table of content
Important This document may not represent best practices for current development, links to downloads and other resources may no longer be valid. Current recommended version can be found here. ArchiveDisclaimer

Microsoft Extensions to C and C++

The following are Visual C++ extensions to the ANSI C and ANSI C++ standards:

Microsoft extends the C++ language with several additional keywords. For a complete list, see C++ Keywords in the C++ Language Reference. Keywords with two leading underscores are Microsoft extensions.

Under the standard (/Za), you need to make an out-of-class definition for data members. For example,

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

Under /Ze, the out-of-class definition is optional for static, const integral, and const enum data members. Only integrals and enums that are static and const can have initializers inside a class; the initializing expression must be a const expression.

To avoid errors when an out-of-class definition is provided (when the out-of-class definition is provided in a header file and the header file is included in multiple source files), you should use selectany. For example:

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

The compiler supports the following two non-ANSI casts:

  • Use of non-ANSI casts to produce l-values:

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

    The preceding example could be rewritten to conform with the ANSI C standard as follows:

    p = ( char * )(( int * )p + 1 );
  • Non-ANSI casting of a function pointer to a data pointer:

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

    To perform the same cast while maintaining ANSI compatibility, you must cast the function pointer to an int before casting it to a data pointer:

    pdata = ( int * ) (int) pfunc;

The compiler supports use of a function declarator that specifies a variable number of arguments, followed by a function definition that provides a type instead:

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

The C compiler supports single-line comments, which are introduced with two forward slash (//) characters:

// This is a single-line comment.

The C compiler supports the following scope-related features:

  • Redefinitions of extern items as static:

    extern int clip();
    static int clip()
  • Use of benign typedef redefinitions within the same scope:

    typedef int INT;
    typedef int INT;
  • Function declarators have file scope:

    void func1()
        extern int func2( double );
    int main( void )
        func2( 4 );    //  /Ze passes 4 as type double
    }                  //  /Za passes 4 as type int
  • Use of block-scope variables initialized with nonconstant expressions:

    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;

The C compiler supports the following data declaration and definition features:

  • Mixed character and string constants in an initializer:

    char arr[5] = {'a', 'b', "cde"};
  • Bit fields with base types other than unsigned int or signed int.

  • Declarators without either a storage class or a type:

    int main( void )
        x = 1;
  • Unsized arrays as the last field in structures and unions:

    struct zero
        char *c;
        int zarray[];
  • Unnamed (anonymous) structures:

        int i;
        char *s;
  • Unnamed (anonymous) unions:

        int i;
        float fl;
  • Unnamed members:

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

The compiler supports inline generation x86 Specific > of the atan, atan2, cos, exp, log, log10, sin, sqrt, and tan functions END x86 Specific when /Oi is specified. For C, ANSI conformance is lost when these intrinsics are used, because they do not set the errno variable.

This is an extension to C++. The following code will compile with /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'

Under /Ze, you have to include iso646.h if you want to use text forms of the following operators:

  • && (and)

  • &= (and_eq)

  • & (bitand)

  • | (bitor)

  • ~ (compl)

  • ! (not)

  • != (not_eq)

  • || (or)

  • |= (or_eq)

  • ^ (xor)

  • ^= (xor_eq)

The following example will output char const (*)[4] under /Za, but char const [4] under /Ze.

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

int main()
    printf_s("%s\n", typeid(&"abc").name());
© 2015 Microsoft