Microsoft 對 C 和 C++ 的擴充功能
以下為 Visual C++ 對 ANSI C 和 ANSI 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 之下,類別外定義對於靜態資料成員、const 整數資料成員和 const 列舉資料成員是選擇性的。 只有 static 和 const 型別的整數和列舉可以在類別 (Class) 之內有初始設定式;這個初始設定運算式必須是 const 運算式。
若要避免提供類別外定義時的錯誤 (在標頭檔中提供類別外定義而標頭檔又包含在多個原始程式檔中),您應該使用 selectany。 例如:
__declspec(selectany) const int CMyClass::max = 5;
轉換
編譯器支援下列兩種非 ANSI 轉換:
使用非 ANSI 轉換以產生左值 (L-Value):
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;
可變長度引數清單
編譯器支援使用指定可變引數數目的函式宣告子 (Declarator),後面接著一個提供型別的函式定義:
void myfunc( int x, ... );
void myfunc( int x, char * c )
{ }
單行註解
C 編譯器支援由雙正斜線 (//) 字元引入的單行註解:
// This is a single-line comment.
範圍
C 編譯器支援下列範圍 (Scope) 相關功能:
重新定義外部項目為 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 以外基底型別 (Base Type) 的位元欄位 (Bit Field)。
沒有儲存類別 (Storage Class) 或沒有型別的宣告子:
x; int main( void ) { x = 1; }
可變大小陣列 (Unsized Array) 做為結構和等位的最後一個欄位:
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 專屬資訊 > atan、atan2、cos、exp、log、log10、sin、sqrt 和 tan 函式 x86 專屬資訊結束。 對於 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)
&= (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());
}