Почему люди так часто используют __ (двойное подчеркивание) в C ++

93

Я просматривал некоторый код C ++ с открытым исходным кодом и заметил много двойных значений под оценками, которые использовались в коде, в основном в начале имен переменных.

return __CYGWIN__;

Просто интересно, есть ли причина для этого, или просто некоторые люди кодируют стили? Я думаю, что мне трудно читать.

Натан В
источник
2
Почему трудно читать? Он разработан в основном как разделитель, как и кавычки. Насколько я помню, он в основном используется для встроенных констант.
Мэтью Шарли,
1
Нет, это не разделитель. Подчеркивания используются, чтобы отличать имена, зарезервированные для реализации, от имен, которые может использовать исходный код пользователя. Пользователи могут делать, #define FOO 1но не должны, #define __FOO__ 1и поэтому реализация может свободно использовать имя __FOO__для своих собственных макросов, переменных, функций и т. Д.
Джонатан
Я думаю, что Мэтью имел в виду, что это стилистически / визуально ограничитель, а не функционально. Это интересная гипотеза, но неверная, учитывая то, что я ранее читал, и ответ Джонатана.
JMI MADISON

Ответы:

128

Из программирования на C ++, правила и рекомендации :

Использование двух подчеркиваний (`__ ') в идентификаторах зарезервировано для внутреннего использования компилятором в соответствии со стандартом ANSI-C.

Подчеркивание (`_ ') часто используется в именах библиотечных функций (таких как« _main »и« _exit »). Во избежание коллизий не начинайте идентификатор с подчеркивания.

Maccullt
источник
1
Это руководство выглядит так, как будто оно было написано до того, как namespaceбыло представлено.
cz
это также было из имперского колледжа в Лондоне, а не из стандарта C ++; это может быть хорошее предложение.
штукатурка
1
@cz Пространства имен не имеют значения. Системный заголовок может определять имя макроса, которое начинается с подчеркивания, например _main.
martinkunev
50

Если они не считают себя «частью реализации», то есть стандартными библиотеками, им не следует этого делать.

Правила довольно конкретны и немного более подробны, чем предлагают некоторые другие.

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

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

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

CB Bailey
источник
1
В C ++ я вижу только [lex.name] и для глобальных имен [global.names]. Можете дать ссылки? спасибо
a.lasram
36

Согласно стандарту C ++ идентификаторы, начинающиеся с одного подчеркивания, зарезервированы для библиотек. Идентификаторы, начинающиеся с двух знаков подчеркивания, зарезервированы для поставщиков компиляторов.

Джеймс Карран
источник
18
Более того: идентификаторы, содержащие в любом месте двойное подчеркивание , зарезервированы. 17.4.3.1.2
Стив Джессоп,
В C ++ я вижу только [lex.name] и для глобальных имен [global.names]. Можете дать ссылки? спасибо
a.lasram
10

Предыдущие комментарии верны. __Symbol__обычно является волшебным токеном, предоставляемым вашим полезным поставщиком компилятора (или препроцессора). Возможно, наиболее широко используются __FILE__и __LINE__, которые расширяются препроцессором C для указания текущего имени файла и номера строки. Это удобно, когда вы хотите зарегистрировать какой-либо сбой утверждения программы, включая текстовое местоположение ошибки.

болото
источник
8

Это то, чего вы не должны делать в «нормальном» коде. Это гарантирует, что компиляторы и системные библиотеки могут определять символы, которые не будут конфликтовать с вашими.

Menkboy
источник
4

Двойные подчеркивания зарезервированы для реализации

Самый популярный ответ цитирует Программирование на C ++: правила и рекомендации :

«Использование двух символов подчеркивания (` __ ') в идентификаторах зарезервировано для внутреннего использования компилятором в соответствии со стандартом ANSI-C ».

Однако, прочитав несколько стандартов C ++ и C, я не смог найти упоминания о том, что символы подчеркивания ограничиваются только внутренним использованием компилятора. Стандарты являются более общими, с двойным подчеркиванием для реализации .

C ++

В C ++ (текущий рабочий проект, по состоянию на 26 мая 2019 г.) говорится lex.name:

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

C

Хотя этот вопрос относится к C ++, я привел соответствующие разделы из стандартов C 99 и 17:

C99 раздел 7.1.3

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

C17 говорит то же самое, что и C99.

Какая реализация ?

Для C / C ++ реализация свободно относится к набору ресурсов, необходимых для создания исполняемого файла из исходных файлов пользователя. Это включает в себя:

  • препроцессор
  • компилятор
  • компоновщик
  • стандартная библиотека

Примеры реализации

В Википедии упоминается ряд различных реализаций C ++ . (без привязки, ctrl + f "реализация")

Вот пример реализации C / C ++ Digital Mars, зарезервировавшей некоторые ключевые слова для их функции.

RemarkableBucket
источник
3

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

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

Шаткий
источник