Spec-Zone.ru › GCC 14

6.7 Ссылка на тип с помощью typeof

Ещё один способ указать тип выражения — с помощью typeof. Синтаксис использования этого ключевого слова похож на sizeof, но конструкция по смыслу работает как имя типа, определённое с помощью typedef.

Существует два способа записи аргумента для typeof: с помощью выражения или с помощью типа. Вот пример с выражением:

typeof (x[0](1))

Предполагается, что x — это массив указателей на функции; описываемый тип — тип значений функций.

Вот пример с именем типа в качестве аргумента:

typeof (int *)

Здесь описываемый тип — это тип указателей на int.

Если вы пишете заголовочный файл, который должен работать при включении в программы на ISO C, используйте __typeof__ вместо typeof. См. Альтернативные ключевые слова.

Конструкцию typeof можно использовать в любом месте, где можно использовать имя typedef. Например, вы можете использовать её в объявлении, в приведении типов или внутри sizeof или typeof.

Операнд typeof оценивается для побочных эффектов только в том случае, если он является выражением с изменяемым типом или именем такого типа.

typeof часто полезно использовать совместно с выражениями операторов (см. Операторы и объявления в выражениях). Вот как их вместе можно использовать для определения безопасной макрокоманды «maximum», которая работает с любым арифметическим типом и оценивает каждый из её аргументов ровно один раз:

#define max(a,b) \
  ({ typeof (a) _a = (a); \
      typeof (b) _b = (b); \
    _a > _b ? _a : _b; })

Причина использования имён, начинающихся с символа подчёркивания, для локальных переменных заключается в предотвращении конфликтов с именами переменных, которые встречаются в выражениях, подставляемых для a и b. В конечном итоге мы надеемся разработать новый синтаксис объявления, который позволит объявлять переменные, область действия которых начинается только после их инициализаторов; это будет более надёжный способ предотвращения подобных конфликтов.

Вот ещё несколько примеров использования typeof:

  • Это объявляет y с типом того, на что указывает x.
    typeof (*x) y;
  • Это объявляет y как массив таких значений.
    typeof (*x) y[4];
  • Это объявляет y как массив указателей на символы:
    typeof (typeof (char *)[4]) y;

    Это эквивалентно следующему традиционному объявлению на C:

    char *y[4];

    Чтобы увидеть значение объявления с использованием typeof, и почему это может быть полезным способом записи, перепишите его с помощью этих макросов:

    #define pointer(T)  typeof(T *)
    #define array(T, N) typeof(T [N])

    Теперь объявление можно переписать так:

    array (pointer (char), 4) y;

    Таким образом, array (pointer (char), 4) — это тип массивов из 4 указателей на char.

Оператор ISO C23 typeof_unqual доступен в режиме ISO C23, и его результат — неатомарная неквалифицированная версия того, что возвращает оператор typeof. Альтернативная запись __typeof_unqual__ доступна во всех режимах C и предоставляет неатомарную неквалифицированную версию того, что возвращает оператор __typeof__. См. Альтернативные ключевые слова.

В GNU C, но не в GNU C++, вы также можете объявить тип переменной как __auto_type. В этом случае объявление должно объявлять только одну переменную, декларатор которой должен быть просто идентификатором, объявление должно быть инициализировано, а тип переменной определяется инициализатором; имя переменной не находится в области видимости до инициализатора. (В C++ для этой цели следует использовать C++11 auto) Используя __auto_type, макрокоманда «maximum» выше могла бы быть написана так:

#define max(a,b) \
  ({ __auto_type _a = (a); \
      __auto_type _b = (b); \
    _a > _b ? _a : _b; })

Использование __auto_type вместо typeof имеет два преимущества:

  • Каждый аргумент макрокоманды появляется только один раз в развёртывании макрокоманды. Это предотвращает экспоненциальный рост размера развёртывания макрокоманды при вложенных вызовах таких макрокоманд внутри аргументов таких макрокоманд.
  • Если аргумент макрокоманды имеет изменяемый тип, он оценивается только один раз при использовании __auto_type, но дважды при использовании typeof.

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Typeof.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API