Значение (информатика)
Значение в программировании — элемент данных, являющийся одним из возможных членов типа данных[1], который может соответствовать некоторому состоянию переменной или константе соответствующего типа. Например, 2
— значение целочисленного типа.
В языках с возможностью присваивания значений переменным возникает необходимость различать r-значения (r-value — содержание) и l-значения (l-value — местоположение) переменной[2].
В декларативных языках значения должны быть ссылочно прозрачными. Это означает, что выходное значение не зависит от местоположения в котором находится выражение (или подвыражение), необходимое для расчёта значения.
L-значения и r-значения
Идея l-значений и r-значений происходит из языков программирования с операторами присваивания, в которых для значений слева (left) и справа (right) от оператора используется различный режим вычисления. l-значение указывает на объект, который сохраняется и за пределами одного выражения. r-значение — это временное значение, которое не сохраняется за пределами использующего его выражения.[3]
Понятия l-значение и r-значение были введены в языке CPL. Понятия в выражениях из r-значений, l-значений и r/l-значений соответствуют следующим режимам параметров: входной параметр (имеет значение), выходной параметр (может быть присвоен), и входной/выходной параметр (имеет значение и может быть присвоен), однако среди языков в зависимости от контекста существуют технические различия.
R-значения и адреса
Во многих языках, в особенности в cи-подобных, l-значения имеют адрес хранения, которые программно доступны исполняемой программе (например, используя оператор адресации «&» в C/C++). Это означает что l-значения являются переменными или разыменованными ссылками на определённые области памяти. R-значения могут быть l-значениями (см. ниже) или не-l-значениями (термин введён для отличия от l-значений). Возьмём к примеру выражение 4 + 9
в языке Си. Во время исполнения программа генерирует значение 13, но поскольку в программе не указано где содержатся эти 13, выражения является не l-значением. С другой стороны, если в Си-программе объявляется переменная x, которой присваивается значение 13, то выражение x
имеет значение 13 и является l-значением.
Сначала термин l-значение обозначал в языке Си то, чему можно что-нибудь присвоить (отсюда и название, указывающее, что это стоит слева (left) от оператора присвоения), однако с тех пор, как в язык было добавлено зарезервированное слово const
(константа), термин теперь звучит как «модифицируемое l-значение». В C++11 существует специальный семантический глиф &&
, указывающий «использовать адрес выражения только компилятору»; то есть адрес не может быть рассчитан оператором &
во время исполнения программы. (см. семантика перемещения).
Непосредственное значение
Такой тип ссылки может использоваться всеми r-значениями, включая как l-значения, так и не-l-значения. В некоторых процессорах имеются инструкции, которые берут непосредственное значение (англ. immediate value). Непосредственное значение хранится как часть инструкции, как правило использующей его для помещения в регистр, либо же добавления или вычитания из него. Другие части инструкции составляет код операции и получатель (регистр). Последний может быть негласным. Значение, не являющееся непосредственным, может находиться в регистре или располагаться в памяти, а инструкция должна содержать прямой или косвенный адрес значения, например, индекс регистра, из которого берётся значение.
L-значение
L-значение в виде выражения указывает на объект[уточнить]. Немодифицируемое (константное) l-значение имеет адрес, но не может быть изменено. В отличие от него, изменяемое l-значение позволяет не только извлекать объект, но и присваивать ему иное значение. R-значение — это любое выражение (в том числе и l-значения), а не-l-значение — это любое выражение, не являющееся l-значением. Примером не-l-значения является непосредственное значение, которое не имеет адреса.
В языке ассемблера
Значение может относиться к любому из доступных типов данных: оно может быть строкой, цифрой или одиночным символом.
Многие процессоры поддерживают несколько размеров непосредственных значений, к примеру, 8 или 16 бит, используя разные коды инструкций для каждого варианта. Если программист вставляет значение, которое не подходит по размеру, то ассемблер выдаёт ошибку «Вне диапазона» (англ. Out of range). Большинство ассемблеров позволяет использовать непосредственные значение в ASCII, десятичном, шестнадцатеричном, восьмеричном или двоичном форматах. Это означает, что ASCII символ 'A'
идентичен значению 65
или 0x41
. Порядок байтов в текстовых строках может различаться в зависимости от типа процессора, версии ассемблера или архитектуры компьютера.
Примечания
- Mitchell, 1996, p. 9.
- Mitchell, 1996, pp. 389–390.
- Lvalues and Rvalues (Visual C++) . MSDN. Дата обращения: 3 сентября 2016.
Литература
- John C. Mitchell. Основы языков программирования (Foundations for Programming Languages). — The MIT Press, 1996. — ISBN 0-262-13321-0.
- Christopher Strachey. Основные понятия в языках программирования (Fundamental Concepts in Programming Languages) // Высший порядок и символьные вычисления. — 2000. — Т. 13. — С. 11—49. — doi:10.1023/A:1010000313106.