Что представляет собой тип, за которым следует _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;