Microsoft extensions to C and C++
Microsoft Visual C++ (MSVC) extends the C and C++ language standards in several ways, detailed in this article.
The MSVC C++ compiler defaults to support for ISO C++14 with some ISO C++17 features and some Microsoft-specific language extensions. For more information on supported features, see Microsoft C/C++ language conformance by Visual Studio version. You can use the /std
compiler option to enable full support for ISO C++17 and ISO C++20 language features. For more information, see /std
(Specify language standard version).
Where specified, some MSVC C++ language extensions can be disabled by use of the /Za
compiler option. In Visual Studio 2017 and later versions, the /permissive-
compiler option disables Microsoft-specific C++ language extensions. The /permissive-
compiler option is implicitly enabled by the /std:c++20
and /std:c++latest
compiler options.
By default, when MSVC compiles code as C, it implements ANSI C89 with Microsoft-specific language extensions. Some of these MSVC extensions are standardized in ISO C99 and later. Most MSVC C extensions can be disabled by use of the /Za
compiler option, as detailed later in this article. You can use the /std
compiler option to enable support for ISO C11 and C17. For more information, see /std
(Specify language standard version).
The standard C runtime library is implemented by the Universal C runtime library (UCRT) in Windows. The UCRT also implements many POSIX and Microsoft-specific library extensions. The UCRT supports the ISO C11 and C17 C runtime library standards, with certain implementation-specific caveats. It doesn't support the full ISO C99 standard C runtime library. For more information, see compatibility in the Universal C runtime library documentation.
Keywords
MSVC adds several Microsoft-specific keywords to C and C++. In the list in Keywords, the keywords that have two leading underscores are MSVC extensions.
Casts
Both the C++ compiler and C compiler support these kinds of non-standard casts:
The C compiler supports non-standard casts to produce l-values. For example:
char *p; (( int * ) p )++; // In C with /W4, both by default and under /Ze: // warning C4213: nonstandard extension used: cast on l-value // Under /TP or /Za: // error C2105: '++' needs l-value
Note
This extension is available in the C language only. You can use the following C standard form in C++ code to modify a pointer as if it's a pointer to a different type.
The preceding example could be rewritten as follows to conform to the C standard.
p = ( char * )(( int * )p + 1 );
Both the C and C++ compilers support non-standard casts of a function pointer to a data pointer. For example:
int ( * pfunc ) (); int *pdata; pdata = ( int * ) pfunc; /* No diagnostic at any level, whether compiled with default options or under /Za */
Variable-length argument lists
Both C and C++ compilers support 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 )
{ }
// In C with /W4, either by default or under /Ze:
// warning C4212: nonstandard extension used: function declaration used ellipsis
// In C with /W4, under /Za:
// warning C4028: formal parameter 2 different from declaration
// In C++, no diagnostic by default or under /Za.
Single-line comments
The C compiler supports single-line comments, which are introduced by using two forward slash (//
) characters:
// This is a single-line comment.
Single-line comments are a C99 feature. They're unaffected by /Za
and cause no diagnostic at any level.
Scope
The C compiler supports the following scope-related features.
Redefinitions of
extern
items asstatic
:extern int clip(); static int clip() {} // In C and C++ with /W4, either by default or under /Ze: // warning C4211: nonstandard extension used: redefined extern to static // In C and C++ under /Za: // error C2375: 'clip': redefinition; different linkage
Use of benign typedef redefinitions within the same scope:
typedef int INT; typedef int INT; // No diagnostic at any level in C or C++
Function declarators have file scope:
void func1() { extern double func2( double ); // In C at /W4: warning C4210: nonstandard extension used: function given file scope } int main( void ) { func2( 4 ); // /Ze passes 4 as type double } // /Za passes 4 as type int
Use of block-scope variables that are initialized by using non-constant 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; }
Data declarations and definitions
The C compiler supports the following data declaration and definition features.
Mixed character and string constants in an initializer:
char arr[6] = {'a', 'b', "cde"}; // In C with /W4, either by default or under /Ze: // warning C4207: nonstandard extension used: extended initializer form // Under /Za: // error C2078: too many initializers
Bit fields that have base types other than
unsigned int
orsigned int
.Declarators that don't have a type:
x; // By default or under /Ze, /Za, /std:c11, and /std:c17, when /W4 is specified: // warning C4431: missing type specifier - int assumed. Note: C no longer supports default-int // warning C4218: nonstandard extension used: must specify at least 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[]; // In C with /W4, either by default, under /Ze, /std:c11, and /std:c17: // warning C4200: nonstandard extension used: zero-sized array in struct/union // Under /Za: // error C2133: 'zarray': unknown size };
Unnamed (anonymous) structures:
struct { int i; char *s; }; // By default or under /Ze, /std:c11, and /std:c17, when /W4 is specified: // warning C4094: untagged 'struct' declared no symbols // Under /Za: // error C2059: syntax error: 'empty declaration'
Unnamed (anonymous) unions:
union { int i; float fl; }; // By default or under /Ze, /std:c11, and /std:c17, when /W4 is specified: // warning C4094: untagged 'union' declared no symbols // Under /Za: // error C2059: syntax error: 'empty declaration'
Intrinsic floating-point functions
Both the x86 C++ compiler and C compiler support inline generation of the atan
, atan2
, cos
, exp
, log
, log10
, sin
, sqrt
, and tan
functions when /Oi
is specified. These intrinsics don't conform to the standard, because they don't set the errno
variable.
ISO646.H
not enabled
Under /Ze
, you have to include iso646.h
if you want to use text forms of the following operators:
Operator | Text form |
---|---|
&& |
and |
&= |
and_eq |
& |
bitand |
| |
bitor |
~ |
compl |
! |
not |
!= |
not_eq |
|| |
or |
|= |
or_eq |
^ |
xor |
^= |
xor_eq |
These text forms are available as C++ keywords under /Za
or when /permissive-
is specified or implied.
See also
/Za
, /Ze
(Disable language extensions)
MSVC compiler options
MSVC compiler command-line syntax