Microsoft-Erweiterungen für C und C++
Nachfolgend sind die Visual C++-Erweiterungen des ANSI C- und des ANSI C++-Standards aufgeführt:
Schlüsselwörter
Microsoft erweitert die Sprache C++ um mehrere Schlüsselwörter. Eine vollständige Liste finden Sie in der C++-Sprachreferenz unter C++ Keywords. Schlüsselwörter mit zwei vorangestellten Unterstrichen sind Microsoft-Erweiterungen.
Definition der Member "static", "const integral" und "const enum" außerhalb von Klassen
In der Standardeinstellung (/Za) müssen Sie Datenmember außerhalb einer Klasse definieren. Beispiel:
class CMyClass {
static const int max = 5;
int m_array[max];
}
...
const int CMyClass::max; // out of class definition
Unter /Ze ist die Definition außerhalb von Klassen für static-Datenmember, const integral-Datenmember und const enum-Datenmember optional. Nur ganze Zahlen und Enumerationen, die als static und const definiert sind, können innerhalb einer Klasse initialisiert werden; der Initialisierungsausdruck muss ein const-Ausdruck sein.
Um Fehler bei der Bereitstellung einer Definition außerhalb einer Klasse zu vermeiden (wenn die Definition außerhalb einer Klasse in einer Headerdatei bereitgestellt wird und die Headerdatei in mehreren Quelldateien eingeschlossen ist), sollten Sie selectany verwenden. Beispiel:
__declspec(selectany) const int CMyClass::max = 5;
Typumwandlungen
Der Compiler unterstützt die beiden folgenden Typumwandlungen, die nicht ANSI-konform sind:
Typumwandlungen zum Erzeugen von l-Werten:
char *p; (( int * ) p )++;
Das vorherige Beispiel könnte folgendermaßen umgeschrieben werden, um dem ANSI C-Standard zu entsprechen:
p = ( char * )(( int * )p + 1 );
Typumwandlung eines Funktionszeigers in einen Datenzeiger:
int ( * pfunc ) (); int *pdata; pdata = ( int * ) pfunc;
Zur Durchführung derselben Typumwandlung unter Beibehaltung der ANSI-Kompatibilität müssen Sie den Funktionszeiger in ein int umwandeln, bevor sie diesen in einen Datenzeiger umwandeln können:
pdata = ( int * ) (int) pfunc;
Argumentlisten variabler Länge
Der Compiler unterstützt die Verwendung eines Funktionsdeklarators, der eine variable Anzahl von Argumenten angibt, gefolgt von einer Funktionsdefinition, die stattdessen einen Typ vorsieht:
void myfunc( int x, ... );
void myfunc( int x, char * c )
{ }
Einzeilige Kommentare
Der C-Compiler unterstützt einzeilige Kommentare, die mit zwei Schrägstrichen (//) eingeleitet werden:
// This is a single-line comment.
Umfang
Der C-Compiler unterstützt, bezogen auf den Gültigkeitsbereich, folgende Features:
Neudefinition von extern-Elementen als static:
extern int clip(); static int clip() {}
Verwendung von typedef-Neudefinitionen ohne Auswirkung innerhalb desselben Gültigkeitsbereichs:
typedef int INT; typedef int INT;
Funktionsdeklaratoren haben Dateigültigkeitsbereich:
void func1() { extern int func2( double ); } int main( void ) { func2( 4 ); // /Ze passes 4 as type double } // /Za passes 4 as type int
Verwendung von Variablen mit Blockgültigkeit, die mit nichtkonstanten Ausdrücken initialisiert sind:
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; }
Datendeklarationen und -definitionen
Der C-Compiler unterstützt die folgenden Datendeklarations- und -definitionsfunktionen:
Gemischte Zeichen- und Zeichenfolgekonstanten in einer Initialisierung:
char arr[5] = {'a', 'b', "cde"};
Bitfelder mit anderen Basistypen als unsigned int oder signed int.
Deklaratoren ohne Speicherklasse und Typ:
x; int main( void ) { x = 1; }
Arrays ohne Größenangabe als letztes Feld in Strukturen und Unions:
struct zero { char *c; int zarray[]; };
Unbenannte (anonyme) Strukturen:
struct { int i; char *s; };
Unbenannte (anonyme) Unions:
union { int i; float fl; };
Unbenannte Member:
struct s { unsigned int flag : 1; unsigned int : 31; }
Systeminterne Gleitkommafunktionen
Der Compiler unterstützt die Inlinegenerierung x86 Specific > der Funktionen atan, atan2, cos, exp, log, log10, sin, sqrt und tanEND x86 Specific, wenn /Oi angegeben ist. Bei C geht die ANSI-Konformität verloren, wenn diese systeminterne Funktionen verwendet werden, weil die errno-Variable von ihnen nicht festgelegt wird.
Übergeben eines nicht konstanten Zeigerparameters an eine Funktion, die einen Verweis auf einen "const"-Zeigerparameter erwartet
Dies ist eine Erweiterung von C++. Der folgende Code wird mit /Ze kompiliert:
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 nicht aktiviert
Unter /Ze müssen Sie iso646.h einschließen, wenn Sie die Textformen der folgenden Operatoren verwenden möchten:
&& (und)
&= (and_eq)
& (bitand)
| (bitor)
~ (compl)
! (not)
!= (not_eq)
|| (or)
|= (or_eq)
^ (xor)
^= (xor_eq)
Die Adresse eines Zeichenfolgenliterals hat den Typ "const char []" und nicht "const char (*) []"
Im folgenden Beispiel wird char const (*)[4] bei Verwendung von /Za, bei Verwendung von /Ze jedoch char const [4] ausgegeben.
#include <stdio.h>
#include <typeinfo>
int main()
{
printf_s("%s\n", typeid(&"abc").name());
}