Error lvalue required as left operand of assignment что значит
Solve error: lvalue required as left operand of assignment
In this tutorial you will know about one of the most occurred error in C and C++ programming, i.e. lvalue required as left operand of assignment.
lvalue means left side value. Particularly it is left side value of an assignment operator.
rvalue means right side value. Particularly it is right side value or expression of an assignment operator.
Example:
In above example a is lvalue and b + 5 is rvalue.
Solve error: lvalue required as left operand of assignment
Now let see some cases where this error occur with code.
Example 1:
When you will try to run above code, you will get following error.
Solution: In if condition change assignment operator to comparison operator, as shown below.
Example 2:
Above code will show the error: lvalue required as left operand of assignment operator.
Here problem occurred due to wrong handling of short hand operator (*=) in findFact() function.
Solution: Just by changing the line ans*i=ans to ans*=i we can avoid that error. Here short hand operator expands like this, ans=ans*i. Here left side some variable is there to store result. But in our program ans*i is at left hand side. It’s an expression which produces some result. While using assignment operator we can’t use an expression as lvalue.
The correct code is shown below.
Example 3:
Above code will show the same lvalue required error.
Reason and Solution: Ternary operator produces some result, it never assign values inside operation. It is same as a function which has return type. So there should be something to be assigned but unlike inside operator.
The correct code is given below.
Some Precautions To Avoid This Error
There are no particular precautions for this. Just look into your code where problem occurred, like some above cases and modify the code according to that.
Mostly 90% of this error occurs when we do mistake in comparison and assignment operations. When using pointers also we should careful about this error. And there are some rare reasons like short hand operators and ternary operators like above mentioned. We can easily rectify this error by finding the line number in compiler, where it shows error: lvalue required as left operand of assignment.
Programming Assignment Help on Assigncode.com, that provides homework ecxellence in every technical assignment.
Comment below if you have any queries related to above tutorial.
Понимание lvalue и rvalue в C и С++
Привет, Хабр! Представляю вашему вниманию перевод статьи Eli Bendersky, Understanding of lvalues and rvalues in C and C++.
От переводчика: предлагаю Вашему вниманию перевод интересной статьи об lvalue и rvalue в языках C/C++. Тема не нова, но знать об этих понятиях никогда не поздно. Статья рассчитана на новичков, либо на программистов переходящих с C (или других языков) на C++. Поэтому будьте готовы к подробному разжёвыванию. Если вам интересно, добро пожаловать под кат
Термины lvalue и rvalue не являются чем-то таким, с чем часто приходится сталкиваться при программировании на C/C++, а при встрече не сразу становится ясным, что именно они означают. Наиболее вероятное место столкнуться с ними — это сообщения компилятора. Например, при компиляции следующего кода компилятором gcc :
Вы уведите нечто следующее:
Согласен, что этот код немного надуманный, и вряд ли Вы будете писать нечто подобное, однако сообщение об ошибке упоминает lvalue — термин, который не так часто увидишь в туториалах по C/C++. Другой пример нагляден при компиляции следующего кода при помощи g++ :
Вы увидите следующую ошибку:
Опять же, в сообщение об ошибке упоминается мистическое rvalue. Что же в C и C++ понимается под lvalue и rvalue? Это и есть тема данной статьи.
Простое определение
Для начала нарочито дадим определения lvalue и rvalue в упрощённой форме. В дальнейшем эти понятия будут рассмотрены под увеличительным стеклом.
lvalue (locator value) представляет собой объект, который занимает идентифицируемое место в памяти (например, имеет адрес).
rvalue определено путём исключения, говоря, что любое выражение является либо lvalue, либо rvalue. Таким образом из определения lvalue следует, что rvalue — это выражение, которое не представляет собой объект, который занимает идентифицируемое место в памяти.
Элементарные примеры
Термины, определённые выше, могут показаться немного нечёткими. Поэтому стоит сразу рассмотреть несколько простых поясняющих примеров. Предположим, мы имеем дело с переменной целого типа:
Оператор присваивания ожидает lvalue с левой стороны, и var является lvalue, потому что это объект с идентифицируемым местом в памяти. С другой стороны, следующие заклинания приведут к ошибкам:
Однако, не все присваивания результату вызова функции ошибочны. Например, использование ссылок в C++ делает это возможным:
Здесь foo возвращает ссылку, которая является lvalue, то есть ей можно придать значение. Вообще, в C++ возможность возвращать lvalue, как результат вызова функции, существенна для реализации некоторых перегруженных операторов. Как пример приведём перегрузку оператора [] в классах, которые реализуют доступ по результатам поиска. Например std::map :
Присваивание mymap[10] работает, потому что неконстантная перегрузка std::map::operator[] возвращает ссылку, которой может быть присвоено значение.
Изменяемые lvalue
Таким образом не всем lvalue можно присвоить значение. Те, которым можно, называются изменяемые lvalue (modifiable lvalues). Формально C99 стандарт определяет изменяемые lvalue как:
Преобразования между lvalue и rvalue
Образно говоря, конструкции языка, оперирующие значениями объектов, требуют rvalue в качестве аргументов. Например, бинарный оператор ‘+’ принимает два rvalue в качестве аргументов и возвращает также rvalue:
Как мы уже видели раньше, a и b оба lvalue. Поэтому в третьей строке они подвергаются неявному преобразованию lvalue-в-rvalue. Все lvalue, которые не являются массивом, функцией и не имеют неполный тип, могут быть преобразованы в rvalue.
Что насчёт преобразования в другую сторону? Можно ли преобразовать rvalue в lvalue? Конечно нет! Это бы нарушило суть lvalue, согласно его определению (Отсутствие неявного преобразования означает, что rvalue не могут быть использованы там, где ожидается lvalue).
Это не означает, что lvalue не могут быть получены из rvalue явным способом. Например, унарный оператор ‘*’ (разыменование) принимает rvalue в качестве аргумента, но возвращает lvalue в качестве результата. Рассмотрим следующий верный код:
Обратно, унарный оператор ‘&’ (адрес) принимает lvalue как аргумент и производит rvalue:
Символ «&» играет несколько другую роль в C++ — он позволяет определить ссылочный тип. Его называют «ссылкой на lvalue». Неконстантной ссылке на lvalue не может быть присвоено rvalue, так как это потребовало бы неверное rvalue-в-lvalue преобразование:
Константным ссылкам на lvalue можно присвоить rvalue. Так как они константы, значение не может быть изменено по ссылке и поэтому проблема модификации rvalue просто отсутствует. Это свойство делает возможным одну из основополагающих идиом C++ — допуск значений по константной ссылке в качестве аргументов функций, что позволяет избежать необязательного копирования и создания временных объектов.
CV-специфицированные rvalues
lvalue (3.10) на тип T, не являющимся функциональным, или массивом, может быть преобразован в rvalue. [. ] Если T не класс, типом rvalue является cv-неспецифицированная версия типа T. Иначе, типом rvalue является T.
Так что же значит «cv-неспецифицированный»? CV-спецификатор — это термин, используемый для описания const и volatile спецификаторов типа.
Каждый тип, который является cv-неспецифицированным полным или неполным объектным типом или типом void (3.9), имеет соответственно три cv-специфицированные версии: тип со спецификатором const, тип со спецификатором volatile и тип со спецификаторами const volatile. [. ] CV-специфицированные и cv-неспецифицированные типы являются различными, однако они имеют одинаковое представление и требования по выравниванию.
Ссылки на rvalue (C++11)
Ссылки на rvalue и сопутствующий концепт семантики переноса являются одним из наиболее мощным инструментом, добавленным в язык C++11. Подробная дискуссия на эту тему выходит за рамки этой скромной статьи (вы можете найти кучу материала, просто погуглив «rvalue references». Вот некоторые ресурсы, которые я нахожу полезными: этот, этот и особенно вот этот), но всё же я хотел бы привести простой пример, потому что считаю, что данная глава является наиболее подходящим место, чтобы продемонстрировать как понимание lvalue и rvalue расширяет наши возможности рассуждать о нетривиальных концепциях языка.
Добрая половина статьи была потрачена на объяснение того, что одним из самых главных различий между lvalue и rvalue является тот факт, что lvalue можно изменять, в то время как rvalue — нет. Что же, C++11 добавляет одну важнейшую характерную особенность в этом различии, разрешая нам иметь ссылки на rvalue и тем самым изменять их в некоторых случаях.
Как пример рассмотрим наипростейшую реализацию динамического массива целых чисел. Давайте посмотрим лишь на методы относящиесе к теме данной главы:
Давайте запустим простой код, который копирует содержимое v1 в v2 :
И вот, что мы увидим:
Что совершенно логично, так как это точно отражает, что происходит внутри оператора присваивания. Но давайте предположим, что мы хотим присвоить v2 некоторое rvalue:
Хотя здесь я только присваиваю значение свеже созданному вектору, это является одной из демонстраций общего случая, когда некоторое временное rvalue создаётся и присваивается v2 (это может случится например, если функция возвращает вектор). Вот что мы увидим на экране:
Ого! Выглядит очень хлопотно. В частности, здесь потребовалась дополнительная пара вызовов конструктора с деструктором, чтобы создать, а потом удалить временный объект. И это печально, так как внутри копирующего оператора присваивания другой временный объект создаётся и удаляется. Дополнительная работа за зря.
Но, нет! C++11 даёт нам ссылки на rvalue, с помощью которых можно реализовать «семантику переноса», а в частности «переносящий оператор присваивания» (теперь понятно почему я всё время называл operator= копирующим оператором присваивания. В C++11 эта разница становится важной). Давайте добавим другой operator= в IntVec :
Двойной асперсанд — это ссылка на rvalue. Он означает как раз то, что и обещает — даёт ссылку на rvalue, который будет уничтожен после вызова. Мы можем использовать этот факт, чтобы просто «стащить» внутренности rvalue — они ему всё равно не нужны! Вот, что выведется на экран:
Хочу только отметить ещё раз, что этот пример только вершина айсберга семантики переноса и ссылок на rvalue. Как вы можете догадаться, это сложная тема с множеством частных случаев и загадок. Я пытался лишь продемонстрировать очень интересное применение различий между lvalue и rvalue в C++. Компилятор очевидно может их различать и позаботится о вызове правильного конструктора во время компиляции.
Заключение
Можно написать много C++ кода, не задумываясь о разногласиях rvalue и lvalue, опуская их как непонятный жаргон компилятора в сообщениях об ошибках. Однако, как я пытался показать в этой статье, лучшее владение этой темы обеспечит более глубокое понимание определённых конструкций C++, и сделает части стандарта C++ и дискуссии между экспертами языка для вас более доступными.
В стандарте C++11 эта тема является ещё более важной, так как C++11 вводит понятия ссылок на rvalue и семантики переноса. Чтобы действительно понять новые особенности языка, строгое понимание rvalue и lvalue просто необходимо.
Ошибка Lvalue required
Пожалуйста помогите исправить ошибку Lvalue required в этой строке: str2=+(s[k-1]);
Ошибка: (19,22): Lvalue required
Пожалуйста помогите найти ошибку! Ошибка: (19,22):Lvalue required Задача несложная, но не как не.
Исправить код: ошибка компиляции lvalue required
#include #include #include main ()< int n,m,t ; float.
Я не смотрел ваш код, но приведенное вами предложение
естественно содержит ошибку, так как имени массива ничего нельзя присваивать. Идентификатору имени массива не выделяется память, поэтому и присваивать ему ничего нельзя. Имя массива всегда является синонимом конкретного адреса памяти, где хранится сам массив, который изменить нельзя.
Грубо говоря, если есть массив
то просто имя массива (т.е. конструкция «a») внутри выражения трактуется как
т.е. берётся адрес самого первого элемента массива и приводится к указателю на тип, который получается, если выкинуть старшее измерение. В нашем случае это будет указатель на < массив из 20 int'ов >. Таким образом, конструкция «a + 3» для данного массива вполне законная и является указателем на элемент a[3][0], приведённом к типу < массив из 20 int'ов >. Т.е. фактически мы получим в результате < массив из 20 int'ов >, который можно подать, например, в процедуру, описанную как
трактуется как тот же самый адрес, а каждая индексация преобразуется в поинтерную арифметику с последующим разыменованием указателя
lvalue and rvalue assignment error [duplicate]
Why is the above code giving me an error, the specific error I get is
lvalue required as left operand of assignment.
9 Answers 9
now x+1=y will throw lvalue required which means left hand side of = should be a variable not a constant
The result of the postincrement operator is a temporary object that has the value before incrementing. You may not assign a temporary object. So this statement is invalid.
You could rewrite it the following way
The statement above is correct.
x++ cannot be use as left operand because it returns a value, not an address.
x++ is r-value, and you cannot assign to it, you can rewrite it as follows: 3 = 5; which makes no sense, you cannot assign 5 to 3.
To achieve what you want, you need to do:
In C++11, with its new sequencing rules, you could also do:
From my understanding the above code should theoretically copy over the value of y into x, then finally increment the value of x after the copy has finished.
x++ evaluates to an r-value (constant). Assignment operator = needs an l-value (variable) as its left operand.
you can’t assign a constant to a constant. x++ = y is not a valid statement in either of C or C++.
x++ results in a temporary object that has x value before the increment. And you cannot assign a temp object.
Examples for clarification:
The core issue is this:
From my understanding the above code should theoretically copy over the value of y into x, then finally increment the value of x after the copy has finished. So it would print out «6».
In fact, the sequencing of the increment is undefined. As in, it is completely undefined as to when x is incremented, except that it must occur before some specific times. Reading or writing x during this period of undefined value is undefined behaviour. That’s why x++ does not return x (an lvalue you can write to) but an rvalue you cannot write to- because there’s simply nothing useful you can do with x until the time it’s guaranteed to be incremented (except take the address, maybe).
You can still break this rule by referring to x twice- for example, consider:
Error lvalue required as left operand of assignment что значит
Опытный
Профиль
Группа: Участник
Сообщений: 654
Регистрация: 25.8.2005
Репутация: нет
Всего: 1
Блин ошибка смешная вышла и не могу понять в чём дело
Код |
struct < volatile unsigned char crc_row_total: 4; >counter; |
struct <
unsigned short CRC_rows_check: 10;
>buffer;
Мне надо в цикле сделать исключающее или для каждого из 10 битов. И результат этой операции присвоить этому же биту. А выдаётся ошибка
lvalue required as left operand of assignment
Эксперт
Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009
Т.е. компилятор офигевает примерно такжэ, как если бы Вы написали 4 = 2;
Эксперт
Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011
Репутация: 12
Всего: 45
Эксперт
Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011
Репутация: 16
Всего: 85
Опытный
Профиль
Группа: Участник
Сообщений: 654
Регистрация: 25.8.2005
Репутация: нет
Всего: 1
Код |
for(counter.byte = 0; counter.byte >= 1;> //Если принимаем не последний бит (т.е не 9-й), то сдвигаем вправо на 1 (наполняем стек) counter.crc_row_total++; //Увеличиваем счётчик битов CRC по строкам buffer.CRC_row = 0; //Обнуляем CRC по строкам, так как приём полубайта завершился и далее будет заново расчёт CRC для следующего полубайта, а для этого исходное состояние CRC должно быть = 0 counter.crc = 0; > counter.crc++; //Увеличиваем счётчик полубайтов. Этот счётчик досчитывает до 4 и сбрасывается в 0 > > |
Сделал как-то так. Появилась другая проблема. Вот этот кусок
В дебаггере дохожу до того что бы buffer.CRC_column юыл равен 1. Он равен 1 в инспекторе переменных видно. Потом дебаггер попадает сюда
buffer.CRC_columns_check |= (1
buffer.CRC_columns_check |= (1
вынести перед первым циклом фор, ну так просто для проверки, то бит установится.
Эксперт
Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011
Репутация: 12
Всего: 45
Наверное, просто захотелось повыпендриваться(((
Цитата(supercelt @ 4.10.2015, 14:35 |
Мне надо в цикле сделать исключающее или для каждого из 10 битов. И результат этой операции присвоить этому же биту. |
без заморочек. И я приношу свои извинения за свой несовершенный код, отголоски которого видны в Вашем коде.
Что подразумевается вот здесь:
Цитата(supercelt @ 4.10.2015, 19:49 |
CRC = бит ^ 1, а далее CRC прошлого вычисления ^ 1 |
А что должно здесь проверяться:
Цитата(supercelt @ 4.10.2015, 19:49 |
Проходит эту строчку и buffer.CRC_columns_check не меняется никак вообще. В этот момент counter.crc = 2. |
Может, второй бит у buffer.CRC_columns_check уже выставлен? Не могли бы Вы описать словами, что Вы хотите сделать с buffer.CRC_columns_check.
Очень подозрительно выглядит и такой код:
Опытный
Профиль
Группа: Участник
Сообщений: 654
Регистрация: 25.8.2005
Репутация: нет
Всего: 1
Алгоритм такой. Нужно высчитать CRC по строкам и столбам. Строки работают. А вот со столбами загвоздка.
Код |
if(conter.bit == 3 || counter.bit == 7) просто вроде как битовые операции работают быстрее чем логические. |
Цитата |
Нет он не выставлен. В инспекторе переменных при отладке видно. что я хочу сделать?, вот что: допустим 1 пришла на 2 итерации цикла, поэтому мы будем работать со 2 битом в переменной buffer.CRC_columns_check. Нужно просто выставить в 1 это 2 бит и всё. А он не выставляется. |
Далее вот по этой строчке
Я думал так: берём текущее значение бита ( counter.crc) переменной buffer.CRC_columns_check, делаем с этим значением искл ИЛИ с 1 и записываем результат в buffer.CRC_column
И пофиг что он будет каждый раз перезаписываться. так и надо
Эксперт
Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007
Репутация: 12
Всего: 72
Эксперт
Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011
Репутация: 16
Всего: 85
Код |
// на входе 5 байт упакованных данных // на выходе будет записано 11 байт (10 байт = 2х5 тетрад + 1 байт паритет по столбцам) void code (const unsigned char * in, unsigned char * out) < static const unsigned char paritytable [16] = <0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0>; unsigned pcolumn = 0; // здесь будет паритет по столбцам for (int i = 0; i > 4) & 0xf; |
Эксперт
Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011
Репутация: 16
Всего: 85
Если это действительно так, то надо будет еще перевернуть тетраду.
Код |
unsigned rever_tetrade (unsigned tetr) < unsigned rever = 0; for (int j = 0; j > j) & 1); return rever; > |
// на входе 5 байт
// на выходе будет записано 11 байт
int code (const unsigned char * in, unsigned char * out)
<
static const unsigned char paritytable [16] = <0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0>;
unsigned pcolumn = 0; // здесь будет паритет по столбцам
for (int i = 0; i > 4) & 0xf);
Опытный
Профиль
Группа: Участник
Сообщений: 654
Регистрация: 25.8.2005
Репутация: нет
Всего: 1
Зачем делается сдвиг на 4 и тут же И с 0x0f?
UPD Не могу понять как применяются эти таблицы. Вы извините, если что, я ещё просто учусь и многого не знаю. Почему в таблице 16 элементов и именно такой порядок нулей и единиц?
Эксперт
Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011
Репутация: 16
Всего: 85
Цитата(supercelt @ 5.10.2015, 20:28 |
Я вот и делаю битовые структуры потому что хочу сэкономить память. |
Упаковывать в битовые структуры целесообразно только большие массивы данных, если там есть смысл.
Упаковывать рабочие переменные не только бесполезно (все равно расчет идет в регистрах процессора, которые всегда кратны байту),
но и вредно, так как очень сильно замедляют все операции.
да и что вы там сэкономите? пару байтов?
Цитата(supercelt @ 5.10.2015, 20:28 |
Не могли бы вы пояснить как работает unsigned h = rever_tetrade ((*in >> 4) & 0xf); |
Цитата(supercelt @ 5.10.2015, 20:28 |
Не могу понять как применяются эти таблицы. |
Опытный
Профиль
Группа: Участник
Сообщений: 654
Регистрация: 25.8.2005
Репутация: нет
Всего: 1
Эксперт
Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011
Репутация: 16
Всего: 85
Цитата(supercelt @ 5.10.2015, 21:44 |
Значит вы не советовали бы собирать 5 байт из полубайтов, а делать массив[10] |
Опытный
Профиль
Группа: Участник
Сообщений: 654
Регистрация: 25.8.2005
Репутация: нет
Всего: 1