Каковы правила использования подчеркивания в идентификаторе 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 зарезервированные идентификаторы

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

  • все идентификаторы, которые начните с подчеркивания и заглавной буквы или другой подчеркивание всегда зарезервировано для любого использования.
  • все идентификаторы, начинающиеся с подчеркивания, резервируются для использования в качестве идентификаторов с области файла в обычным и имя тега пробелы.
  • каждое имя макроса в любом из следующих подклассов (включая будущую библиотеку directions) зарезервирован для использования, как указано, если любой из его связанных заголовков включен; если явно указано иное (см. 7.1.4).
  • все идентификаторы с внешней связью в любом из следующих подклассов (включая будущие направления библиотеки) всегда зарезервированы для использования в качестве идентификаторов с внешними связь.154
  • каждый идентификатор с областью действия файла, указанной в любом из следующих подклассов (включая будущие направления библиотеки) зарезервирован для использования в качестве имени макроса и идентификатора с объем файла в том же пространстве имен, если любой из заголовков включен.

другие идентификаторы не зарезервированы. Если программа объявляет или определяет идентификатор в контекст, в котором он зарезервирован (кроме как разрешено в 7.1.4), или определяет зарезервированный идентификатор как имя макроса, поведение не определено.

если программа удаляет (с #undef) любое определение макроса идентификатора в первом группа, перечисленная выше, поведение не определено.

154) список зарезервированных идентификаторов с внешней связью включает errno, math_errhandling, setjmp и va_end.

могут применяться другие ограничения. Например, стандарт POSIX резервирует много идентификаторов, которые могут отображаться в обычном коде:

  • имена, начинающиеся с большой буквы E после цифры или прописной буквы:
    • может использоваться для дополнительного кода ошибки имена.
  • имена, которые начинаются с is или to за ним следует строчная буква
    • может использоваться для дополнительных функций тестирования и преобразования символов.
  • имена, которые начинаются с LC_ за ним следует заглавная буква
    • может использоваться для дополнительных макросов, указывающих атрибуты локали.
  • имена всех существующих математических функций с суффиксом с f или l зарезервированы
    • для соответствующих функций, которые работают с float и длинными двойными аргументами соответственно.
  • имена, которые начинаются с SIG за ним следует заглавная буква зарезервированы
    • для дополнительных имен сигналов.
  • имена, которые начинаются с SIG_ за ним следует заглавная буква зарезервированы
    • дополнительные сигнал действия.
  • имена, начинающиеся с str, mem или wcs за строчной буквой следуют зарезервированы
    • для дополнительных функций строки и массива.
  • имена, начинающиеся с PRI или SCN далее следуют любые буквы или X зарезервированы
    • для дополнительных макросов спецификатора формата
  • имена, которые заканчиваются _t несколько зарезервированный
    • для дополнительных имен типов.

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


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

после выполнения исследования по этой статье я больше не заканчиваю свои идентификаторы с _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 - одно подчеркивание означает "частный", а двойные подчеркивания обычно зарезервированы для использования компилятором.