Что означает двойное подчеркивание (__const) в C?

extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
 __THROW;

Я нашел указанное выше определение функции в /usr/include/netinet/ether.h в ящике Linux.

Может кто-нибудь объяснить, что означают двойные подчеркивания перед константой (ключевое слово), addr (идентификатор) и, наконец, __THROW.

Ответ 1

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

Дано:

extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
__THROW;

Обозначение __const позволяет предположить (несколько маловероятно), что компилятор использует этот код для поддержки прототипов нотации, но не имеет правильного понимания стандартного ключевого слова C89 const. Макросы autoconf все еще могут проверить, поддерживает ли компилятор поддержку const; этот код можно использовать со сломанным компилятором, который не имеет такой поддержки.

Использование __hostname и __addr - это мера защиты для вас, пользователя заголовка. Если вы скомпилируете GCC и параметр -Wshadow, компилятор предупредит вас, когда какие-либо локальные переменные будут затенять глобальную переменную. Если функция использовала только hostname вместо __hostname, и если бы у вас была функция с именем hostname(), было бы затенение. Используя имена, зарезервированные для реализации, нет конфликта с вашим законным кодом.

Использование __THROW означает, что код может при определенных обстоятельствах быть объявлен с какой-то "спецификацией броска". Это не стандарт C; это больше похоже на С++. Но код может использоваться с компилятором C, если один из заголовков (или сам компилятор) определяет __THROW для пустого или для некоторого расширения, специфичного для компилятора стандартного синтаксиса C.


В разделе 7.1.3 стандарта C (ISO 9899: 1999) говорится:

7.1.3 Зарезервированные идентификаторы

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

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

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

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

- Все идентификаторы с внешней связью в любом из следующих подпунктов (включая будущие направления библиотек) всегда зарезервированы для использования в качестве идентификаторов с внешними связь. 154)

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

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

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

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


См. также Каковы правила использования подчеркивания в идентификаторе на С++; многие одинаковые правила применяются как к C, так и к С++, хотя встроенное правило двойного подчеркивания находится только на С++, как указано в начале этого ответа.

Ответ 2

Имена с двумя ведущими подчеркиваниями зарезервированы для использования в реализации. Это не обязательно означает, что они внутренние как таковые, хотя они часто бывают.

Идея заключается в том, что вам не разрешено использовать какие-либо имена, начиная с __, поэтому реализация может свободно использовать их в таких местах, как расширения макросов, или в именах расширений синтаксиса (например, __gcnew is не является частью С++, но Microsoft может добавить его в С++/CLI, уверенный, что никакой существующий код не должен иметь что-то вроде int __gcnew; в нем, которое прекратило бы компиляцию).

Чтобы узнать, что означают эти конкретные расширения, т.е. __const, вам нужно обратиться к документации для вашего конкретного компилятора/платформы. В этом конкретном случае вам следует, вероятно, рассмотреть прототип в документации (например, http://www.kernel.org/doc/man-pages/online/pages/man3/ether_aton.3.html) в качестве функционального интерфейса и игнорировать __const и __THROW, которые отображаются в фактическом заголовке.

Ответ 3

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

Ответ 4

Подчеркивание в __const означает, что это ключевое слово является расширением компилятора и использование его не переносимо (ключевое слово const было добавлено в C в более поздней редакции, 89, я думаю). __THROW также является своего рода расширением, я предполагаю, что он определяется определенным __ атрибутом __ (что-то), если используется gcc, но я не уверен в этом и слишком ленив, чтобы проверить. __addr может означать все, что программист хотел, чтобы это означало, это просто имя.