Spec-Zone.ru › GCC 15

6.12.5 Обращение к типу с помощью typeof

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

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

typeof (x[0](1))

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

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

typeof (int *)

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

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

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

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

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

#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++ для этой цели следует использовать auto из C++11.) С помощью __auto_type приведенный выше макрос «максимум» можно записать так:

#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-15.3.0/gcc/Typeof.html

Spec-Zone.ru

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