Спецификатор типа
В C , C++ и D языках программирования — квалификатор типа это ключевое слово , которое применяется к типу , в результате чего получается уточненный тип. Например, const int
является квалифицированным типом, представляющим постоянное целое число, а int
— соответствующий неквалифицированный тип, просто целое число. В D они известны как конструкторы типов , по аналогии с конструкторами в объектно-ориентированном программировании .
Квалификаторы типа — это способ выражения дополнительной информации о значении через систему типов и обеспечения правильности использования данных. Квалификаторы типа обычно не используются за пределами семейства языков C/C++: многие языки имеют обозначение констант, но выражают это посредством константной привязки имени («переменная, которая не меняется»), а не через систему типов. ; см. альтернативы ниже.
По языку
[ редактировать ]С/С++
[ редактировать ]По состоянию на 2014 год [update] и C11 , в стандарте C есть четыре квалификатора типа: const
( С89 ), volatile
( С89 ), restrict
( С99 ) и _Atomic
( C11 ) – последний имеет частное имя, чтобы избежать конфликта с именами, определяемыми пользователем. [1] Первые два из них, const
и volatile
, также присутствуют в C++ и являются единственными квалификаторами типа в C++. Таким образом, в C++ термин « cv -квалифицированный тип» (для констант и изменчивых ) часто используется для обозначения «квалифицированного типа», в то время как термины « c -квалифицированный тип» и « v -квалифицированный тип» используются, когда только один из квалификаторы актуальны.
Из них const
на сегодняшний день является самым известным и наиболее используемым, появляющимся в стандартных библиотеках C и C++ и встречающимся при любом значительном использовании этих языков, которое должно удовлетворять const-correctness . Остальные квалификаторы используются для низкоуровневого программирования и, хотя и широко там используются, типичными программистами используются редко. Однако какое-то время volatile
использовался некоторыми программистами C++ для синхронизации во время потоковой обработки, хотя это не поощрялось и теперь не работает в большинстве компиляторов.
Д
[ редактировать ]В D конструкторы типов: const
, immutable
, shared
, и inout
. immutable
является более сильным вариантом const
, обозначая данные, которые никогда не могут изменить свое значение, в то время как const
указывает данные, которые не могут быть изменены с помощью этой ссылки: это постоянное представление возможно изменяемых данных. shared
используется для общих данных в многопоточности (как volatile
кратко использовался в C++). inout
— это подстановочный знак, используемый, чтобы позволить функциям, которые не изменяют данные (и, следовательно, имеют дело только с неполным типом данных), возвращать тот же полный тип, что и входные данные. const
и immutable
также могут использоваться в качестве спецификаторов классов хранения.
Синтаксис
[ редактировать ]В C и C++ тип задается в объявлении функции или объявлении переменной путем указания одного или нескольких спецификаторов типа и, при необходимости, квалификаторов типа. Например, целочисленную переменную можно объявить как:
int x;
где int
является спецификатором типа. Целочисленную переменную без знака можно объявить как:
unsigned int x;
где оба unsigned
и int
являются спецификаторами типа. Постоянная целочисленная переменная без знака может быть объявлена как:
const unsigned int x;
где const
является квалификатором типа, который определяет квалифицированный тип x
является const unsigned int
и неквалифицированный тип unsigned int
.
Объявления переменных также имеют необязательный спецификатор класса хранения . Хотя это отдельная тема, отличная от типа const
в объявлении переменной также считается, что это имеет значение для класса хранения, а именно то, что она может храниться в постоянной памяти.
Неустойчивая корректность
[ редактировать ]Другой квалификатор в C и C++, volatile
, указывает, что объект может быть изменен чем-то внешним по отношению к программе в любое время и поэтому должен перечитываться из памяти при каждом обращении к нему.
Квалификатор чаще всего встречается в коде, который напрямую манипулирует оборудованием (например, во встроенных системах и драйверах устройств ), а также в многопоточных приложениях (хотя в этом контексте часто используется неправильно; см. внешние ссылки на изменчивую переменную ). Его можно использовать точно так же, как const
в объявлениях переменных, указателей, ссылок и функций-членов, и фактически volatile
иногда используется для реализации аналогичной стратегии проектирования по контракту, которую Андрей Александреску называет volatile
-правильность, [2] хотя это гораздо реже, чем const
-правильность. volatile
квалификатор также может быть удален с помощью const_cast
, и его можно комбинировать с const
квалификатор, как в этом примере:
// Set up a reference to a read-only hardware register that is
// mapped in a hard-coded memory location.
const volatile int & hardwareRegister = *reinterpret_cast<int*>(0x8000);
int currentValue = hardwareRegister; // Read the memory location
int newValue = hardwareRegister; // Read it again
hardwareRegister = 5; // Error, cannot write to a const location
Потому что hardwareRegister
является volatile
, нет никакой гарантии, что оно будет содержать одно и то же значение при двух последовательных чтениях, даже если программист не сможет его изменить. Семантика здесь указывает на то, что значение регистра доступно только для чтения, но не обязательно неизменно.
История
[ редактировать ]Понятие квалификатора типа было введено вместе с примером readonly
(позже переименованный const
) Бьярна Страуструпа во внутреннем техническом меморандуме Bell Labs от 1981 года, [3] и реализован на C с помощью Classes , предшественника C++ . [4] Что касается мотивации, Страуструп пишет: [4]
- «Он выполнял две функции: как способ определения символической константы, которая подчиняется правилам области видимости и типа (то есть без использования макроса), и как способ считать объект в памяти неизменяемым».
const
затем был принят в C как часть стандартизации и появляется в C89 (и последующих версиях) вместе с другим квалификатором типа, volatile
, который был изобретен комитетом по стандарту ANSI C (X3J11). [5] volatile
появился к 1985 году; [6] и первое использование было при компиляции ядра UNIX для MIPS , чтобы обеспечить оптимизированную компиляцию, предотвращая применение обычных оптимизаций к изменчивым переменным. [7] Еще один квалификатор, noalias
, было предложено на заседании комитета X3J11 в декабре 1987 года, но было отклонено; ее цель была в конечном итоге достигнута restrict
квалификация в C99. Мотивация для noalias
был дополнением к volatile
, а именно, что это указывало на возможность выполнения даже обычно небезопасных оптимизаций. Ричи не очень поддерживал квалификаторы типов, утверждая, что они «не несут своего веса», но в конечном итоге не выступал за их удаление из стандарта; [8] он был против noalias
однако его исключили из проекта.
В Java нет квалификаторов типов, и они явно опущены. const
: предложение 1999 года о его добавлении было отклонено, в частности, потому, что добавление его постфактум, а затем изменение стандартной библиотеки для ее последовательного использования привело бы к нарушению совместимости. [9] Однако Java изначально оставляла открытой возможность реализации const
, заметно в этом const
Это зарезервированное слово , хотя на самом деле оно не используется в качестве ключевого слова . Вместо этого в Java есть объектно-ориентированное ключевое слово final
, который используется для квалификации атрибутов (а затем и для локальных переменных) как констант, но не для квалификации типов.
Альтернативы
[ редактировать ]Другие языки используют другой подход, рассматривая константность как свойство идентификатора ( или привязки имени ), а не типа. Таким образом, такие языки имеют постоянные идентификаторы (соответствующие «переменным», которые не изменяются) с одиночным присвоением, но не имеют понятия константной корректности: поскольку постоянство не является частью типа, вероятность несоответствия типов отсутствует. Примеры включают Ada 83 с постоянными объектами и constant
ключевое слово, [10] [а] и Java с final
ключевое слово.
Примечания
[ редактировать ]- ^ В стандарте Ada это называется « зарезервированным словом »; см. эту статью для использования.
Ссылки
[ редактировать ]- ^ C11: Новый стандарт C , Томас Плам
- ^ «Generic<Programming>: Volatile-Correctness, лучший друг многопоточного программиста, или как заставить ваш компилятор обнаруживать за вас условия гонки», Андрей Александреску в журнале пользователей C/C++ Форум экспертов C++
- ^ Бьерн Страуструп , «Расширения концепции типа языка C», внутренний технический меморандум Bell Labs, 5 января 1981 г.
- ^ Перейти обратно: а б Соперничество между братьями и сестрами: C и C++ , Бьёрн Страуструп , 2002, стр. 5
- ^ Деннис М. Ритчи , « Развитие языка C. Архивировано 10 января 2015 г. на archive.today », 2003: «X3J11 также представил множество небольших дополнений и корректировок, например, квалификаторы типа const и voluty и немного другие правила продвижения по типу».
- ^ Он появляется в примечаниях к техническому докладу заседания Европейской группы пользователей систем UNIX (EUUC) «Проект стандарта ANSI для языка программирования C», написанному Майком Банаханом, 13 сентября 1985 г., как напечатано в информационном бюллетене группы пользователей австралийских систем Unix (AUUGN). ), Том 6, № 6 , с. 73
- ^ Джон Мэши (16 августа 1991 г.). «Re: RISC против CISC? Называть вещи своими именами?» . Группа новостей : comp.arch . Usenet: [электронная почта защищена] .
- ^ «Позвольте мне начать с того, что я не уверен, что даже квалификаторы до декабря («const» и «летучие») имеют свой вес; я подозреваю, что то, что они добавляют к стоимости изучения и использования языка, не является В частности, «Неустойчивость» является дополнением к эзотерическим приложениям, и ее главное достоинство состоит в том, что почти каждый может забыть о ней, она одновременно более полезна и более навязчива; вы не можете не узнать об этом из-за его присутствия в интерфейсе библиотеки. Тем не менее, я не выступаю за отмену квалификаторов, хотя бы потому, что уже слишком поздно».
- ^ JDK-4211070: Java должна поддерживать константные параметры (например, C++) для поддержки кода [ sic ]
- ^ 1815А , 3.2.1. Объявления объектов :
«Объявленный объект является константой, если в объявлении объекта появляется зарезервированное слово константа; тогда объявление должно включать явную инициализацию. Значение константы не может быть изменено после инициализации. Формальные параметры режима в подпрограммах и записях, а также общие параметры формальные параметры режима in также являются константами; параметр цикла является константой внутри соответствующего цикла; подкомпонент или фрагмент константы является константой.