2012-06-19 2 views
1

В C, есть ли способ идентифицировать значения и lvalues?C Как определить rvalue и lvalue?

Некоторые из них легко идентифицировать, в задании левое значение равно lvalue, а значение справа - rvalue.

Но другие сценарии, идентификация с таким правилом сложна.

Например: *p++ и i++ (где p - это указатель на целое число, а i - целое число) - как определить, является ли оно значением rvalue или lvalue? Контекст ++*p++ работает пока ++i++ не с i++ - это rvalue (как говорят серьезные ребята).

Как определить rvalue и lvalue в выражении?

+0

Я думаю, что это хороший вопрос, но что вы имеете в виду под «идентифицировать» ? Вам нужен полный список операций и возвращаете ли они значения l или r? Способ сказать из функции sig? Способ увидеть каждую строку кода, в которой есть lvalue или rvalue? – djechlin

+0

@djechlin, «Определить» Я имею в виду, могу ли я определить, работает ли фрагмент кода, просмотрев исходный код (без необходимости усложнения). Без исчерпывающего списка есть метод, который я могу применить для определения rvalue и lvalue? Но если существует исчерпывающий список, это будет работать для меня. –

+0

Я думаю, вы должны начать с забывания «rvalue = значение справа», это просто неправильно. – qdii

ответ

2

именующее (от левой стороны значения (LHS)) в чем-то, что относится к памяти (или регистр) хранения, и что можно присваивать значения. *p++ является именующего, так как это разыменованный указатель (т.е. относится к расположению в памяти, что ptr указует в то время как стоимость самого ptr является адресом этого места) и ++*ptr++ на самом деле означают: *ptr = *ptr + 1; ptr = ptr + 1; - он увеличивает значение указует на на ptr, а затем увеличивает значение указателя. i++ не является lvalue, так как это значение i увеличивается на 1 и не относится к местоположению в памяти. Вы можете думать о таких значениях, как final - их нельзя модифицировать и их можно использовать только в качестве значений для назначения lvalues ​​. Вот почему они называются rvalues ​​ (от правая часть (RHS) значение).

LHS и RHS относятся к обеим сторонам выражения присваивания A = B;. A является LHS и B является RHS.

0

От Deitel и Deitel:

имена переменных называются lvalues ​​ (для «левых ценностей»), потому что они могут быть использованы в левой части оператора присваивания. Константы называются rvalues ​​ (для «правильных значений»), поскольку они могут использоваться только с правой стороны оператора присваивания. Обратите внимание, что lvalues ​​ также может использоваться как rvalues ​​, но не наоборот.

x = 3; /* here, x is an lvalue */ 
c = x; /* and in the next line it is an rvalue */ 
+0

Похоже, он знал это и хочет знать более полные способы их идентификации. – djechlin

2

Термин именующее был с C (и был перенесен на C++ и расширена позже). Для начала не было rvalue. В проекте I (N1570) перечислены два вхождения термина rvalue - один раз в сноске # 64 и один раз в индексе.

В двух словах: В мире C у вас есть два типа объектов - lvalues ​​ и все остальное.

Обратите внимание, что сноски не являются частью стандарта, но они могут предоставить некоторые полезные сведения. Здесь идет сноска 64:

64) Название «„именующего“» приходит первоначально из выражения присваивания E1 = E2, в которой левое операнде E1 требуется, чтобы быть (изменяемой) именующей. Это, пожалуй, лучше считается представляющим значение «локатор» . То, что иногда называют «rvalue», указано в этом Международном стандарте, описанном как «значение выражения».

Очевидным примером lvalue является идентификатор объекта. В качестве дополнительного примера, если E является унарным выражением , которое является указателем на объект, * E - это значение l, которое обозначает объект, к которому указывает E.

Это дает хорошее начало. Теперь имейте в виду, что выражение создается из объектов (и операторов, но мы немного поправимся), и есть две основные вещи, о которых вам нужно беспокоиться при работе с объектами: Type и Value. Давайте посмотрим, что делает стандарт говорит об ограничениях типа, то (6.3.2.1/p1):

Именующего выражением является выражением (с типом объекта, кроме пустоты), которые потенциально обозначает объект; 64), если lvalue не определяет объект при его оценке, поведение не определено.

Кроме того, обратите внимание на следующую строку, которая важна:

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

это так, именующего может быть использовано в качестве замены для данного типа (мы увидим это тоже). Далее, давайте посмотрим на контекстах, где объект являетсяименующего (6.3.2.1/2):

когда операнд оператора SizeOf, оператора _Alignof, то унарный оператор &, оператор ++, оператор-оператор или левый операнд. оператор или оператор назначения

Итак, это те операторы, которым необходимо следить. Во всех других случаях:

именующей, который не имеет типа массива не преобразуется в значение , хранящемся в указанном объекте (и больше не именующий); это называется lvalue преобразование.

Существует два специальных типа: массивы и обозначения функций. Эти распада т.е. являются преобразуется в выражение с типом «„указатель на тип“», который указывает к начальному элементу массива объекта и не является именующее/«указатель на функцию типа возвращения».(Помните, мы остановились на том, что lvalues ​​ может работать как типы - это именно то, что они делают с sizeof и _Alignof!)