Что означает «зарезервировано для любого использования»? - PullRequest
0 голосов
/ 17 сентября 2018

ПРИМЕЧАНИЕ. Это вопрос , хотя я добавил на тот случай, если какой-либо эксперт по C ++ может предоставить обоснование или историческую причину, по которой C ++ использует формулировку, отличную от C.


В спецификации стандартной библиотеки C у нас есть этот нормативный текст, C17 7.1.3 Зарезервированные идентификаторы (выделено мной):

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

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

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

В то время как вторая фраза выше, касающаяся единственного нижнего подчеркивания, кажется, направлена ​​на реализацию?

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

Примечательно, что C ++ имеет совершенно другую формулировку:

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

(см. Каковы правилаиспользуя подчеркивание в идентификаторе C ++? )

Возможно, это путаница между C и C ++, и языки здесь разные?

Ответы [ 6 ]

0 голосов
/ 27 февраля 2019

Уже несколько месяцев, но остаётся одна точка, к которой другие не обратились.

Ваш вопрос можно посмотреть в противоположном направлении.Стандарт позволяет реализации (как вы заметили) использовать символ, такой как _Foo, но, что более важно, тем самым запрещает реализации использовать foo.Последний зарезервирован для вашего использования.

Для понимания, предположим, что в будущем стандарте C введено новое ключевое слово _Foo.Гипотетическая реализация уже использовала этот символ, так что же происходит?

Ответ:

  1. Сначала реализация еще не внедрила новый стандарт.До реализации новый стандарт не имеет практического эффекта.

  2. Позже, в рамках реализации нового стандарта, реализация тихо меняет каждый _Foo на _Bar.

Нет проблем.

Фактически, если вы думаете об этом таким образом, вы можете сказать, что стандартное резервирование таких слов является почти единственным способомэто может зарезервировать их.

0 голосов
/ 18 сентября 2018

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

#ifdef __ACME_COMPILER
#define near __near
#else
#define near
#endif

int near foo;

для объявления идентификатора foo с использованием квалификатора __near, если код обрабатывается в компиляторе Acme (который предположительно будет поддерживать такую ​​вещь), но также будет совместим с другими компиляторами, которые не будут требовать или извлекать выгоду из использование такой директивы. Ничто не помешает соответствующей реализации определить __ACME_COMPILER и интерпретировать __near как «запуск ядерных ракет», но качественная реализация не должна изо всех сил ломать код, подобный приведенному выше. Если реализация не знает, что должно означать __ACME_COMPILER, обработка ее как любого другого неизвестного идентификатора позволит ему поддерживать полезные конструкции, подобные приведенным выше.

0 голосов
/ 17 сентября 2018

C имеет несколько контекстов, в которых символ может иметь определение:

  • Пространство имен макросов,
  • Пространство формальных имен аргументов макроса (это пространствоспецифичен для каждого функционально-подобного макроса),
  • Пространство обычных идентификаторов,
  • Пространство имен тегов,
  • Пространство меток (это пространство относится ккаждая функция) и
  • Пространство членов структуры / объединения (это пространство специфично для каждой структуры / объединения).

Что означает «зарезервировано для любого использования», что означает, что пользователькод в совместимой программе не может использовать символы 1 , которые начинаются со знака подчеркивания, за которым следует заглавная буква или другое подчеркивание в любом из указанных выше контекстов.Сравните с идентификаторами, которые начинаются с одного подчеркивания, но сопровождаются строчными буквами или цифрами.Это относится ко второму классу идентификаторов, которые начинаются с подчеркивания.Пользовательский код может может использовать эти идентификаторы в качестве имен макро-аргументов, в качестве меток или в качестве имен членов структуры / объединения.

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


1 Стандарт не совсем означает «не могу использовать».Стандарт поощряет программное использование небольшого числа имен, которые начинаются с двойного подчеркивания.Например, совместимая реализация требуется для определения __STDC_VERSION__, __FILE__, __LINE__ и __func__.Версия стандарта 2011 года даже приводит пример предположительно совместимой программы, которая ссылается на __func__.

0 голосов
/ 17 сентября 2018

Что касается различий в формулировках C и C ++, я публикую здесь свое небольшое исследование в качестве ссылки:

  • Раннее K & R C 1-е издание имеет следующий текст:

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

  • K & R 2nd edition добавило Приложение B, в котором рассматривается стандартная библиотека, где мы можем прочитать

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

  • Ранние проекты ANSI C, а также "C90" ISO 9899: 1990 имеют тот же текст, что и в текущем стандарте ISO.

  • Однако самые ранние черновики C ++ имеют другой текст, как отмечает @hvd, возможно, разъяснение стандарта C. С ПРОЕКТ: 20 сентября 1994 :

    17.3.3.1.2 Глобальные имена
    ...
    Каждое имя, которое начинается со знака подчеркивания и либо с заглавной буквы, либо другого подчеркивания (2.8) Зарезервировано для реализации для любого использования

Таким образом, очевидно, что формулировка «зарезервировано для любого использования» была изобретена комитетом ANSI / ISO C90, тогда как комитет C ++ несколько лет спустя использовал более четкую формулировку, аналогичную той, что была в предстандартной книге K & R.


Обоснование C99 V5.10 говорит об этом ниже 7.1.3:

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

Это делает намерение комитета совершенно ясным: «зарезервировано для любого использования» означает «зарезервировано для исполнителя».


Также следует отметить, что текущий стандарт C имеет следующий нормативный текст в другом месте, в 6.2.5:

Там также может быть определенные в реализации расширенные целочисленные типы со знаком 38)

, где информативная нога 38 гласит:

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

0 голосов
/ 17 сентября 2018

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

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

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

Стандарт продолжается, однако:

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

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

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

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

Стандарт C ++ работает аналогичным образом, хотя в гамбите он немного более явный:

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

Я подозреваю, что разница в формулировках сводится к стандарту C ++, просто яснее о том, как расширения должны работать. Тем не менее, ничто в стандарте C не мешает реализации делать то же самое. (И все мы в основном игнорируем требование, чтобы компилятор предупреждал вас каждый раз, когда вы используете __declspec.)

0 голосов
/ 17 сентября 2018

В стандарте C значение термина «зарезервировано» определяется в 7.1.3p2, непосредственно под цитируемым списком, который вы цитируете:

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

Подчеркну мое: зарезервированные идентификаторы накладывают ограничение на программу , а не на реализацию. Таким образом, общая интерпретация & ndash; зарезервированные идентификаторы могут использоваться реализацией для любых целей & ndash; правильно для C.

Я не придерживался стандарта C ++ и больше не чувствую себя способным его интерпретировать.

...