Microsoft C 和 C++ 扩展
以下是对 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 int 或 signed 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 Specific 的 atan、atan2、cos、exp、log、log10、sin、sqrt 和 tan 函数。 对于 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());
}