Программирование ARM gcc: использование typeof Sat, May 04 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

gcc: использование typeof Печать
Добавил(а) microsin   

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

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

typeof (x[0](1))

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

Пример с использованием в качестве аргумента имени типа:

typeof (int *)

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

Если вы пишете заголовочный файл, который должен работать при подключении к программам ISO C, то вместо typeof пишите __typeof__ (см. описание альтернативных ключевых слов [2]).

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

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

Использование typeof часто полезно вместе с операторными выражениями (statement expressions, см. [3]). Ниже показан пример, как безопасно определить макрос "максимума", который работает с любыми арифметическими типами, и оценивает каждый из своих аргументов ровно 1 раз:

#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.

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

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

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

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

[Ссылки]

1. Referring to a Type with typeof site:gcc.gnu.org.
2. gcc: альтернативные ключевые слова.
3. gcc: операторы и объявления в выражениях.

 

Комментарии  

 
0 #1 John Doe 02.08.2023 12:11
Макрос с __auto_type:

#define max(a,b)
({ __auto_type _a = (a);
__auto_type _b = (b);
_a > _b ? _a : _b; })
Цитировать
 

Добавить комментарий


Защитный код
Обновить

Top of Page