Поделиться через


Расширения Майкрософт для языков C и C++

Далее перечислены расширения стандартов ANSI C и ANSI C++ в Visual C++.

Ключевые слова

Корпорация Майкрософт добавила в язык C++ несколько дополнительных ключевых слов. Полный список ключевых слов см. в разделе C++ Keywords справочнике поя языку C++. Ключевые слова с двумя подчеркиваниями в начале являются расширениями Майкрософт.

Определение статических постоянных целочисленных элементов (static, const или enum) вне класса

По стандарту (/Za) элементы данных следует определять вне класса. Например:

class CMyClass  {
   static const int max = 5;
   int m_array[max];
}
...
const int CMyClass::max;   // out of class definition

По стандарту /Ze определение вне класса необязательно для статических (static), целых постоянных (const int) и постоянных перечислений (const enum) элементов данных. Только у статических и постоянных целочисленных элементов и перечислений могут быть инициализаторы внутри класса, а инициализирующее выражение должно быть константой.

Чтобы избегать ошибок при определении вне класса (когда определение вне класса расположено в файле заголовка, а он включается в несколько исходных файлов) необходимо использовать 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;
    

Списки аргументов переменной длины

Компилятор поддерживает использование декларатора функции, в котором указывается переменное количество аргументов, за которыми следует определение функции, предоставляющей тип:

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;
    }
    

Встроенные функции с плавающей запятой

Компилятор поддерживает генерирование встроенных функций, ориентированных на системы x86, atan, atan2, cos, exp, log, log10, sin, sqrt и tan END x86 Specific, если указан параметр /Oi. Для языка 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 (*) []

В следующем примере выводится тип char const (*)[4] с использованием параметра /Za, но если используется параметр /Ze, выводится тип char const [4].

#include <stdio.h>
#include <typeinfo>

int main()
{
    printf_s("%s\n", typeid(&"abc").name());
}

См. также

Ссылки

/Za, /Ze (отключить расширения языка)

Параметры компилятора

Настройка параметров компилятора