Что представляет собой тип, за которым следует _t (underscore-t)?
Это похоже на простой вопрос, но я не могу найти его с помощью поиска или Google. Что означает тип, за которым следует _t
? Например,
int_t anInt;
Я вижу это в коде C, предназначенном для работы с аппаратным обеспечением - я не могу не думать, что они связаны.
Ответы
Ответ 1
Как отметил Дуглас Майл, в основном это название типа. Следовательно, вам было бы неразумно заканчивать имена переменных или функций "_t
", так как это может вызвать некоторую путаницу. Как и size_t
, стандарт C89 определяет wchar_t
, off_t
, ptrdiff_t
и, возможно, некоторые другие, о которых я забыл. Стандарт C99 определяет множество дополнительных типов, таких как uintptr_t
, intmax_t
, int8_t
, uint_least16_t
, uint_fast32_t
и т.д. Эти новые типы формально определены в <stdint.h>
, но чаще всего вы будете использовать <inttypes.h>
, который (необычно для стандартных заголовков C) включает <stdint.h>
. Он (<inttypes.h>
) также определяет макросы для использования с printf()
и scanf()
.
Как отметил Мэтт Кертис, в суффиксе нет никакого значения для компилятора; это конвенция, ориентированная на человека.
Однако следует также отметить, что POSIX определяет множество дополнительных имен типов, заканчивающихся на '_t
', и сохраняет суффикс для реализации. Это означает, что если вы работаете над системами, связанными с POSIX, определение ваших имен типов с помощью соглашения не рекомендуется. Система, над которой я работаю, сделала это (более 20 лет); мы регулярно запускаем системы, определяющие типы с тем же именем, что и мы.
Ответ 2
Это соглашение, используемое для именования типов данных, например, с помощью typedef
:
typedef struct {
char* model;
int year;
...
} car_t;
Ответ 3
_t
обычно обертывает непрозрачное определение типа.
GCC просто добавляет имена, заканчивающиеся на _t
, в зарезервированное пространство имен, которое вы не можете использовать, чтобы избежать конфликтов с будущими версиями Standard C и POSIX (руководство библиотеки GNU C). После некоторых исследований я, наконец, нашел правильную ссылку в стандарте POSIX (1003.1, Обоснование (Информативное)):
B.2.12 Типы данных
Требование о том, чтобы дополнительные типы, определенные в этом разделе, заканчивались на '' _t, были вызваны проблема загрязнения космического пространства. Трудно определить тип (где этот тип не один определенный IEEE Std 1003.1-2001) в одном файле заголовка и использовать его в другом без добавления символов в пространство имен программы. Чтобы позволить разработчикам предоставлять свои собственные типы, все требуемые приложения должны избегать символов, заканчивающихся на '' _t, что позволяет чтобы обеспечить дополнительные типы. Поскольку основное использование типов содержится в определении которые могут (и во многих случаях) быть добавлены к структурам, определенным в IEEE Std 1003.1-2001, необходимость в дополнительных типах является убедительной.
В двух словах, стандарт говорит, что есть хорошие шансы расширить список стандартных типов, поэтому стандарт ограничивает пространство имен _t
для собственного использования.
Например, ваша программа соответствует POSIX 1003.1 Проблемы 6, и вы определили тип foo_t
. POSIX 1003.1 Проблемы 7 в конечном итоге выпущены с новым определенным типом foo_t
. Ваша программа не соответствует новой версии, что может быть проблемой. Ограничение использования _t
предотвращает рефакторинг кода. Таким образом, если вы нацелены на соответствие POSIX, вы должны обязательно избегать _t
, как утверждает стандарт.
Боковое примечание: лично я пытаюсь придерживаться POSIX, потому что я думаю, что он дает хорошие основы для чистого программирования. Более того, я очень люблю Стиль кодирования Linux (глава 5). Есть несколько веских причин, почему нельзя использовать typedef. Надеюсь эта помощь!
Ответ 4
Это стандартное соглашение об именах для типов данных, обычно определяемое typedefs. Многие C-коды, относящиеся к аппаратным регистрам, используют стандартные имена, определенные для C99, для типов данных с фиксированным размером без подписей и без знака. Как соглашение, эти имена находятся в стандартном файле заголовка (stdint.h) и заканчиваются на _t.
Ответ 5
Это означает тип. size_t
- тип размера.
Ответ 6
_t
не имеет особого значения. Однако для добавления суффикса _t
к typedef's стало общепринятым.
Вы можете быть более знакомы с обычными методами C для именования переменных... Это похоже на то, как это распространено, чтобы придерживаться ap в начале для указателя и использовать знак подчеркивания перед глобальными переменными (это немного менее распространены) и использовать имена переменных i
, j
и k
для временных переменных цикла.
В коде, где важны размер и порядок слов, очень часто используются явно определенные типы определенных типов, такие как BYTE
WORD
(обычно 16 бит) DWORD
(32 бит).
int_t
не так хорош, потому что определение int
варьируется между платформами - так чей int
вы соответствуете? (Хотя в наши дни большинство PC-ориентированных разработок рассматривают его как 32 бита, многие вещи для разработки без ПК по-прежнему обрабатывают int как 16 бит).
Ответ 7
Это просто соглашение, которое означает "тип". Это ничего особенного для компилятора.
Ответ 8
Если вы имеете дело с кодом аппаратного интерфейса, автор кода, который вы ищете, может определить int_t
как целое число определенного размера. Стандарт C не присваивает конкретный размер типу int
(это зависит от вашего компилятора и целевой платформы, возможно), и использование определенного типа int_t
позволит избежать этой проблемы с переносимостью.
Это особенно важно для кода аппаратного интерфейса, который может быть причиной того, что вы впервые заметили там соглашение.
Ответ 9
Было несколько хороших объяснений по этому вопросу. Просто добавьте еще одну причину для переопределения типов:
Во многих встроенных проектах все типы переопределяются, чтобы правильно указать данный размер для типов и улучшить переносимость на разных платформах (например, компиляторы типов аппаратных средств).
Еще одна причина заключается в том, чтобы сделать ваш код переносимым в разных ОС и избежать конфликтов с существующими типами в ОС, которые вы интегрируете в свой код. Для этого обычно добавляется уникальный (как возможно) префикс.
Пример:
typedef unsigned long dc_uint32_t;