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 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:
x; int main( void ) { x = 1; } -
Unsized arrays as the last field in structures and unions:
struct zero { char *c; int zarray[]; }; -
Unnamed (anonymous) structures:
struct { int i; char *s; }; -
Unnamed (anonymous) unions:
union { int i; float fl; }; -
Unnamed members:
struct s { unsigned int flag : 1; unsigned int : 31; }
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'
}