Extensiones de Microsoft para C y C++
Actualización: noviembre 2007
A continuación se relacionan las extensiones de Visual C++ para las normas ANSI C y ANSI C++:
Palabras clave
Microsoft amplía el lenguaje C++ con varias palabras clave adicionales. Para obtener una lista completa, vea C++ Keywords en la Referencia del lenguaje de C++. Las palabras clave con dos caracteres de subrayado iniciales son extensiones de Microsoft.
Definición fuera de clase de miembros integral (o enum) de tipo static y const
Con la opción estándar (/Za), debe crear una definición fuera de clase para los miembros de datos. Por ejemplo,
class CMyClass {
static const int max = 5;
int m_array[max];
}
...
const int CMyClass::max; // out of class definition
Con /Ze, la definición fuera de clase es opcional para los miembros de datos enum o integral de tipo static y const. Solamente los miembros integral y enum de tipo static y const pueden tener inicializadores dentro de una clase; la expresión de inicialización debe ser una expresión const.
Para evitar errores cuando se suministra una definición fuera de clase (cuando la definición se proporciona en un archivo de encabezado y éste se incluye en varios archivos de código fuente), utilice selectany. Por ejemplo:
__declspec(selectany) const int CMyClass::max = 5;
Conversiones de tipo
El compilador acepta las dos siguientes conversiones de tipo no ANSI:
Uso de conversiones de tipo no ANSI para generar valores l:
char *p; (( int * ) p )++;
El ejemplo anterior podría modificarse para adaptarlo a la norma ANSI C como sigue:
p = ( char * )(( int * )p + 1 );
Conversión de tipo no ANSI de un puntero a función a un puntero a datos:
int ( * pfunc ) (); int *pdata; pdata = ( int * ) pfunc;
Para realizar la misma conversión a la vez que se mantiene la compatibilidad con ANSI, debe convertir el puntero a función en int antes de convertirlo en un puntero a datos:
pdata = ( int * ) (int) pfunc;
Listas de argumentos de longitud variable
El compilador admite el uso de un declarador de función que especifique un número de argumentos variable, seguido de una definición de función que proporcione un tipo:
void myfunc( int x, ... );
void myfunc( int x, char * c )
{ }
Comentarios en una línea
El compilador de C acepta comentarios en una sola línea, que se introducen con dos caracteres de barra diagonal (//):
// This is a single-line comment.
Ámbito
El compilador de C acepta las siguientes funciones relacionadas con el ámbito:
Redefiniciones de elementos extern como static:
extern int clip(); static int clip() {}
Uso de redefiniciones typedef benignas dentro del mismo ámbito:
typedef int INT; typedef int INT;
Los declaradores de función tienen ámbito de archivo:
void func1() { extern int func2( double ); } int main( void ) { func2( 4 ); // /Ze passes 4 as type double } // /Za passes 4 as type int
Uso de variables con ámbito de bloque inicializadas con expresiones no constantes:
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; }
Declaraciones y definiciones de datos
El compilador de C acepta las siguientes funciones de declaración y definición de datos:
Constantes de caracteres y cadenas mezcladas en un inicializador:
char arr[5] = {'a', 'b', "cde"};
Campos de bits con tipos base distintos de unsigned int o signed int.
Declaradores sin clase de almacenamiento o tipo:
x; int main( void ) { x = 1; }
Matrices sin tamaño como último campo en estructuras y uniones:
struct zero { char *c; int zarray[]; };
Estructuras sin nombre (anónimas):
struct { int i; char *s; };
Uniones sin nombre (anónimas):
union { int i; float fl; };
Miembros sin nombre:
struct s { unsigned int flag : 1; unsigned int : 31; }
Funciones intrínsecas de punto flotante
El compilador admite la generación en línea Específico de x86 de las funciones atan, atan2, cos, exp, log, log10, sin, sqrt y tanEspecífico de END x86 cuando se especifica /Oi. Para C, la compatibilidad con ANSI se pierde cuando se utilizan estas funciones intrínsecas, puesto que no definen la variable errno.
Pasar un parámetro de puntero no Const a una función que espera una referencia a un parámetro de puntero Const
Esto es una extensión de C++. El código siguiente se compila con /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 no habilitado
Con /Ze debe incluir iso646.h si desea usar formas de texto de los operadores siguientes:
&& (y)
&= (and_eq)
& (bitand)
| (bitor)
~ (compl)
! (not)
!= (not_eq)
|| (or)
= (or_eq)
^ (xor)
^= (xor_eq)
La dirección de un literal de cadena tiene tipo const char [], no const char (*) []
El siguiente ejemplo escribirá un char const (*)[4] con la opción /Za y un char const [4] con /Ze.
#include <stdio.h>
#include <typeinfo>
int main()
{
printf_s("%s\n", typeid(&"abc").name());
}