Каковы правила использования подчеркивания в идентификаторе C++?
В C++ часто называют переменные-члены с некоторым префиксом, чтобы обозначить тот факт, что они являются переменными-членами, а не локальными переменными или параметрами. Если вы пришли из фона MFC, вы, вероятно, будете использовать m_foo
. Я тоже видел myFoo
иногда.
C# (или, возможно, просто .NET), похоже, рекомендует использовать только подчеркивание, как в _foo
. Это разрешено стандартом C++?
5 ответов:
правила (которые не изменились в C++11):
- зарезервированных в любой области, в том числе для использования в качестве макросов реализации :
- идентификаторы, начинающиеся с подчеркивания, за которым сразу следует заглавная буква
- идентификаторы, содержащие соседние подчеркивания (или"двойное подчеркивание")
- зарезервировано в глобальном пространстве имен:
- идентификаторы, начинающиеся с подчеркивание
- кроме того, все
std
пространство имен защищены. (Однако вы можете добавлять специализации шаблонов.)из стандарта 2003 C++:
17.4.3.1.2 глобальные имена [lib.глобальный.имена]
определенные наборы имен и сигнатур функций всегда зарезервированы для реализации:
- каждое имя, содержащее двойное подчеркивание (
__
) или начинается с подчеркивания, за которым следует заглавная буква (2.11) зарезервирована для реализации для любого использования.- каждое имя, начинающееся с подчеркивания зарезервированы для реализации для использования в качестве имени в глобальном пространстве имен.165
165) такие имена также зарезервированы в пространстве имен
::std
(17.4.3.1).потому что C++ основан на стандарте C (1.1 / 2, C++03) и C99 является нормативным ссылка (1.2 / 1, C++03) они также применяются, начиная со стандарта 1999 C:
7.1.3 зарезервированные идентификаторы
каждый заголовок провозглашает и определяет все идентификаторы, перечисленные в соответствующем разделе, и при необходимости объявляет или определяет идентификаторы, перечисленные в соответствующем подразделе будущих направлений библиотеки, и идентификаторы, которые всегда зарезервированы либо для любого использования, либо для использования в качестве идентификаторов области действия файла.
- все идентификаторы, которые начинающиеся с символа подчеркивания и прописной буквы или другой подчеркивание всегда зарезервировано для любого использования.
- все идентификаторы, начинающиеся с подчеркивания, резервируются для использования в качестве идентификаторов с областью действия файла как в обычном, так и в пространстве имен тегов.
- каждое имя макроса в любом из следующих подклассов (включая будущую библиотеку направления) зарезервирован для использования, как указано, если любой из связанных с ним заголовки включены; если только явно указано иное (см. 7.1.4).
- все идентификаторы с внешней связью в любом из следующих подклассов (включая будущие направления библиотеки) всегда зарезервированы для использования в качестве идентификаторов с внешними связь.154
- каждый идентификатор с областью действия файла, перечисленной в любом из следующих подразделов (включая будущие направления библиотеки) зарезервирован для использования в качестве имени макроса и в качестве идентификатора с объем файла в том же пространстве имен, если любой из его связанных заголовков включен.
другие идентификаторы не зарезервированы. Если программа объявляет или определяет идентификатор в a контекст, в котором он зарезервирован (кроме разрешенного в 7.1.4), или определяет зарезервированный идентификатор как имя макроса, поведение не определено.
если программа удаляет (с
#undef
) любое макроопределение идентификатора в первом группа, перечисленная выше, поведение не определено.154) список зарезервированных идентификаторов с внешней связью включает
errno
,math_errhandling
,setjmp
иva_end
.могут применяться и другие ограничения. Например, в стандарте POSIX оставляет за собой множество идентификаторов, которые являются вероятно, чтобы показать в нормальный код:
- имена, начинающиеся с большой буквы
E
после цифры или прописной буквы:
- может использоваться для дополнительного кода ошибки имена.
- имена, которые начинаются с
is
илиto
с последующей строчной буквой
- может использоваться для дополнительных функций тестирования и преобразования символов.
- имена, которые начинаются с
LC_
за которым следует прописная буква
- может использоваться для дополнительных макросов, определяющих атрибуты локали.
- имена всех существующих математических функций с суффиксом с
f
илиl
зарезервированы
- для соответствующих функций, которые работают с плавающими и длинными двойными аргументами соответственно.
- имена, которые начинаются с
SIG
после прописной буквы зарезервированы
- для дополнительных имен сигналов.
- имена, которые начинаются с
SIG_
после прописной буквы зарезервированы
- дополнительные сигнал действия.
- имена, начинающиеся с
str
,mem
илиwcs
после строчной буквы зарезервированы
- для дополнительных функций строк и массивов.
- имена, начинающиеся с
PRI
илиSCN
за ним следует любая строчная буква илиX
зарезервированы
- для дополнительных макросов спецификатора формата
- имена, которые заканчиваются
_t
are зарезервированный
- для дополнительных имен типов.
хотя использование этих имен для ваших собственных целей прямо сейчас может не вызвать проблем, они действительно повышают вероятность конфликта с будущими версиями этого стандарта.
лично я просто не начинать идентификаторы с символа подчеркивания. Новое дополнение к моему правилу: Не используйте двойные подчеркивания в любом месте, что легко, поскольку я редко использую подчеркивание.
после выполнения исследование по этой статье я больше не заканчиваю свои идентификаторы с
_t
поскольку это зарезервировано стандартом POSIX.правило о любом идентификаторе, заканчивающемся на
_t
меня это очень удивило. Я думаю, что это стандарт POSIX (пока не уверен), который ищет разъяснения и официальную главу и стих. Это из руководство GNU libtool, список зарезервированных имен.CesarB предоставил следующую ссылку на POSIX 2004 зарезервирован символы и примечания", что многие другие зарезервированные префиксы и суффиксы ... можно найти там. Этот POSIX 2008 зарезервированные символы определены здесь. Ограничения несколько более тонки, чем те, что выше.
правила, позволяющие избежать столкновения имен, содержатся как в стандарте C++ (см. книгу Страуструпа), так и упоминаются гуру C++ (Саттер и т. д.).
персональные правила
потому что я не хотел иметь дело с делами, и хотел простое правило, я разработал персональный тот, который является одновременно простым и правильным:
При именовании символа вы избежите столкновения с компилятором / ОС / стандартными библиотеками, если ты:
- никогда не начинайте с символа подчеркивания
- никогда не называйте символ с двумя последовательными подчеркиваниями внутри.
конечно, размещение кода в уникальном пространстве имен также помогает избежать столкновения (но не защищает от злых макросов)
примеры
(Я использую макросы, потому что они более загрязняют код символов C/C++, но это может быть что угодно от имени переменной до класса имя)
#define _WRONG #define __WRONG_AGAIN #define RIGHT_ #define WRONG__WRONG #define RIGHT_RIGHT #define RIGHT_x_RIGHT
выдержки из проекта C++0x
С n3242.pdf файл (я ожидаю, что окончательный стандартный текст будет похож):
17.6.3.3.2 глобальные имена [global.имена]
определенные наборы имен и сигнатур функций всегда зарезервированы для реализации:
- каждое имя, содержащее двойное подчеркивание _ _ или начинающееся с подчеркивания, за которым следует заглавная буква (2.12) предназначен для выполнения для любого использования.
- каждое имя, начинающееся с подчеркивания зарезервированы для реализации для использования в качестве имени в глобальном пространстве имен.
а также:
17.6.3.3.5 пользовательские буквенные суффиксы [usrlit.суффикс]
идентификаторы буквенных суффиксов, которые не начинаются с подчеркивания, зарезервированы для будущей стандартизации.
этот последний предложение сбивает с толку, если вы не считаете, что имя, начинающееся с одного подчеркивания и сопровождаемое строчной буквой, будет в порядке, если не определена в глобальном пространстве имен...
с MSDN:
использование двух последовательных символов подчеркивания ( __ ) в начале идентификатора или одного подчеркивания, сопровождаемый заглавной буквы, зарезервированы для реализаций C++ во всех областях. Не следует использовать одно начальное подчеркивание, за которым следует строчная буква для имен с областью действия файла из-за возможных конфликтов с текущими или будущими зарезервированными идентификаторами.
Это означает, что вы можете использовать одинарное подчеркивание в качестве префикса переменной-члена, если за ним следует строчная буква.
Это, по-видимому, взято из раздела 17.4.3.1.2 стандарта C++, но я не могу найти исходный источник для полного стандарта в интернете.
см. также этот вопрос.
Что касается другой части вопроса, то обычно ставится подчеркивание на конец имени переменной, чтобы не конфликтовать ни с чем внутренним.
Я делаю это даже внутри классов и пространств имен, потому что тогда мне нужно запомнить только одно правило (по сравнению с "в конце имени в глобальной области и начале имени везде").
да, подчеркивания могут использоваться в любом месте идентификатора. Я считаю, что правила таковы: любой из a-z, A-Z, _ в первом символе и те + 0-9 для следующих символов.
префиксы подчеркивания являются общими в коде C - одно подчеркивание означает "частный", а двойные подчеркивания обычно зарезервированы для использования компилятором.