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

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

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

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

4 ответа

Решение

В C символы, начинающиеся со знака подчеркивания, за которым следует либо заглавная буква, либо другое подчеркивание, зарезервированы для реализации. Вы, как пользователь 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++. Но код может использоваться с компилятором C, если один из заголовков (или сам компилятор) определяет __THROW пусто или к некоторому специфичному для компилятора расширению стандартного синтаксиса C.


Раздел 7.1.3 стандарта C (ISO 9899:1999) гласит:

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

Другие вопросы по тегам