Зарезервировал ли стандарт ISO 9899 какое-либо использование суффикса _t для идентификаторов? - PullRequest
1 голос
/ 08 июля 2019

Я могу прочитать во многих книгах и других SO-вопросах, что стандарт может расширить набор идентификаторов, таких как size_t или int32_t, поэтому он резервирует любое использование суффикса _t для идентификаторов.

Это правда?

Я не смог найти ничего, что препятствовало бы использованию этого суффикса в стандарте ISO9899: 1999 , но этот стандарт трудно читать: (

Ответы [ 3 ]

8 голосов
/ 08 июля 2019

Нет, это не так.

Стандарт оставляет за собой право добавлять идентификаторы , начиная с int или uint и заканчивая _t в заголовке stdint.h (§7.31.10).Эти идентификаторы технически зарезервированы только в том случае, если этот заголовок включен, но поскольку он почти всегда есть, их следует рассматривать как зарезервированные.

В общем, стандартные идентификаторы резервов, определенные в стандартных заголовках или упомянутые в будущих направлениях длястандартные заголовки (§7.31).Идентификаторы, имеющие внешнюю связь (библиотечные функции), зарезервированы для этого использования (что не мешает вам использовать их в качестве локальных или статических переменных, например).Если заголовок библиотеки включен, то его идентификаторы зарезервированы для использования в области видимости файла.Подробности см. В §7.1.3.

Как указывается в этом разделе, единственными безоговорочно зарезервированными идентификаторами являются те, которые начинаются с подчеркивания, за которым следует заглавная буква или второе подчеркивание.

При чтениистандартно, важно понимать разницу между контекстами, в которых зарезервировано имя:

  • Зарезервировано для любого использования (идентификаторы начинаются со знака подчеркивания, за которым следует другое подчеркивание илизаглавная буква): эти идентификаторы могут использоваться реализацией в виде макросов или специальных символов, которые обрабатываются компилятором каким-то особенным образом.Никогда не определяйте один из них в вашем коде, а используйте те, которые документированы только так, как указано в документации.Не используйте такой символ, если он не документирован, даже если вы видите, что он используется в заголовке какой-то стандартной библиотеки.Или чужой код.

  • Зарезервировано в области видимости файла (другие идентификаторы, начинающиеся с подчеркивания, не являются частью какого-либо стандартного заголовка): эти идентификаторы не будут использоваться какмакросы, и вы не должны также определять их как макросы.Вы можете использовать их в качестве локальных переменных, меток, параметров и struct или union членов.Лично я бы этого не сделал, но это разрешено.Я предпочитаю ставить подчеркивание в конце идентификатора, который используется в некотором внутреннем контексте.

  • Зарезервировано в области видимости файла и в качестве имени макроса (любой идентификатор, упомянутый в стандартном заголовке , включенном , в том числе в пункте будущих направлений): Опять же, поскольку эти идентификаторы могут быть макросами, вы должны рассматривать их как запретные, если вы #include связализаголовок.Стандарт позволяет вам #undef идентификатор, используемый в качестве имени функции в стандартной библиотеке, хотя вы можете обнаружить, что производительность снижается, поскольку макрос оборачивает конструкцию с эквивалентной семантикой, но оптимизированной производительностью.

  • Зарезервировано для использования в качестве идентификатора с внешней связью (любой идентификатор, определенный в заголовке любой стандартной библиотеки как имеющий внешнюю связь, независимо от того, включен ли этот заголовок, включая идентификатор errno): самый слабыйпредварительный заказ.Если вы не включите связанный заголовок, вы можете использовать такой идентификатор даже в области видимости файла, если он не виден снаружи.Так что это может быть область видимости файла static или член перечисления или тег struct или union.Смысл этого пункта не в том, чтобы позволить вам сознательно скрывать имя стандартной библиотечной функции.Скорее, это защищает вас от будущих добавлений в стандартную библиотеку, которые могут экспортировать внешний символ, который вы используете в настоящее время.Конечно, если ваше текущее использование является внешне видимым идентификатором, у вас все еще будет проблема в будущем.Но в целом, внешне видимые символы должны иметь префикс с именем пакета, чтобы избежать конфликтов имен с другими библиотеками.


Сказав все это, неразумно использовать идентификатор, который выглядит так, как будто он может быть стандартным идентификатором.Posix содержит список из более чем сотни шаблонов имен идентификаторов, которые он может использовать в будущем, включая все идентификаторы, заканчивающиеся _t, поэтому, если вы ожидаете, что ваш код будет использоваться в среде Posix, вам следует избегать этих имен,И хотя в будущих версиях стандарта C может не быть добавлено новых имен типов к существующим заголовкам (кроме упомянутых выше целочисленных имен типов), на самом деле вы не хотите исключать использование любых таких новых типов, поскольку они вполне могут быть полезны.(И, согласно комментарию @JensGustedt, который знает о работе рабочей группы C гораздо больше, чем я, в существующих заголовках в C2x будет пара новых имен типов.)

4 голосов
/ 08 июля 2019

Стандартный C позволяет вам использовать суффикс _t, если вы не получите токен, начинающийся с двойного подчеркивания. (Обратите внимание, что C ++ ограничивает это еще и тем, что двойное подчеркивание не допускается нигде в токене; его следует соблюдать, если вы ожидаете, что ваш код достигнет C ++.)

Это POSIX, который резервирует _t.

3 голосов
/ 08 июля 2019

Суффикс _t не зарезервирован ISO 9899 как таковой. Будущие указания библиотеки для ревизии C11 говорят только о том, что ( C11 7.31.10 ):

  1. Имена типов по умолчанию , начинающиеся с int или uint и заканчивающиеся _t, могут быть добавлено к типам, определенным в заголовке <stdint.h>. [...]

Тем не менее, существует очень много типов с суффиксом _t, определенным в C11:

char16_t, char32_t, clock_t, cnd_t, constraint_handler_t, div_t, double_t, errno_t, fenv_t, fexcept_t, float_t, fpos_t imaxdiv_t, int_fastN_t, int_leastN_t, intmax_t, intN_t, intptr_t, ldiv_t, lldiv_t, max_align_t, mbstate_t, mtx_t, ptrdiff_t, rsize_t, sig_atomic_t, size_t, thrd_start_t, thrd_t, time_t, tss_dtor_t, tss_t, uint_fastN_t, uint_least N_t, uintmax_t, uintN_t, uintptr_t, wchar_t, wctrans_t, wctype_t, wint_t

POSIX, с другой стороны, резервирует суффикс _t для использования в системе. Обоснование POSIX 1003.1 имеет этот отрывок:

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

В целом, учитывая, что есть вероятность, что вы захотите использовать свой код C в системе POSIX сейчас или позже, чтобы избежать использования _t для своих собственных типов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...