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

StackOverflow https://stackoverflow.com/questions/1449181

  •  11-09-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

Данный:

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

В __const обозначения существуют для того, чтобы учесть возможность (несколько маловероятную) того, что компилятор, с которым используется этот код, поддерживает обозначения прототипов, но не имеет правильного понимания стандартного ключевого слова C89 constautoconf макросы все еще могут проверять, имеет ли компилятор рабочую поддержку для 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 также является своего рода расширением, я предполагаю, что оно определяется для некоторого __атрибута__(чего-то), если используется gcc, но я не уверен в этом и слишком ленив, чтобы проверять.__addr может означать все, что хотел программист, это просто имя.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top