Почему строка это lvalue, а число это rvalue?
От: Максим Рогожин Россия  
Дата: 01.09.18 07:45
Оценка:
Привет!


int main() {
   cout << "1024" << endl; // "1024" - lvalue?
   cout << 1024 << endl;   // 1024 - rvalue?
}
Re: Почему строка это lvalue, а число это rvalue?
От: σ  
Дата: 01.09.18 13:06
Оценка:
Потому что тут сказано так http://eel.is/c++draft/expr.prim.literal
Re[2]: Почему строка это lvalue, а число это rvalue?
От: Максим Рогожин Россия  
Дата: 01.09.18 14:50
Оценка:
Здравствуйте, σ, Вы писали:

σ>Потому что тут сказано так http://eel.is/c++draft/expr.prim.literal


Объяснить это как-то можно?
Re[3]: Почему строка это lvalue, а число это rvalue?
От: cures Россия cures.narod.ru
Дата: 01.09.18 15:35
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Объяснить это как-то можно?


Возможно, потому, что строковый литерал имеет адрес в памяти, значит, формально, туда можно что-то присвоить. Хотя в плюсах компилятор может положить (и обычно кладёт) эти литералы в память только на чтение. Например, ((char *) "abc") [0] = 'd'; синтаксически правильно, хотя и UB.
А как Вы это выяснили и на что это влияет?
Re[4]: Почему строка это lvalue, а число это rvalue?
От: Максим Рогожин Россия  
Дата: 01.09.18 18:50
Оценка:
Здравствуйте, cures, Вы писали:

C>Возможно, потому, что строковый литерал имеет адрес в памяти, значит, формально, туда можно что-то присвоить. Хотя в плюсах компилятор может положить (и обычно кладёт) эти литералы в память только на чтение. Например, ((char *) "abc") [0] = 'd'; синтаксически правильно, хотя и UB.


Так число 1024 компилятор ведь тоже кладет в память (только на чтение), поэтому у него тоже должен быть адрес в памяти. Тогда и 1024 получается lvalue.

C>А как Вы это выяснили и на что это влияет?

Да прочитал в статье какой-то. На что может повлиять сам бы хотел знать.
Re[5]: Почему строка это lvalue, а число это rvalue?
От: Draqon  
Дата: 01.09.18 19:36
Оценка: +2
Здравствуйте, Максим Рогожин, Вы писали:

МР>Так число 1024 компилятор ведь тоже кладет в память (только на чтение), поэтому у него тоже должен быть адрес в памяти. Тогда и 1024 получается lvalue.


Не факт. Число может быть в регистре и адреса не иметь (т.к. rvalue). Возможно, т.к. строка — это массив, её решили сделать lvalue, т.к. она всегда в памяти и имеет адрес (это догадка, на самом деле не знаю).
Re[5]: Почему строка это lvalue, а число это rvalue?
От: Михaил  
Дата: 02.09.18 05:10
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Так число 1024 компилятор ведь тоже кладет в память (только на чтение), поэтому у него тоже должен быть адрес в памяти. Тогда и 1024 получается lvalue.


Нет, число кладется в обычную секцию данных, а не в ro (если не обьявите как const)
А строки кладутся в ro data, потому что они константные по умолчанию (так и называются — “string constant”.

C>>А как Вы это выяснили и на что это влияет?

МР>Да прочитал в статье какой-то. На что может повлиять сам бы хотел знать.

Вот здесь объясняется, почему С-строки — const по умолчанию:
https://softwareengineering.stackexchange.com/questions/294748/why-are-c-string-literals-read-only
Re[6]: Почему строка это lvalue, а число это rvalue?
От: σ  
Дата: 02.09.18 06:27
Оценка: +3
МР>>Так число 1024 компилятор ведь тоже кладет в память (только на чтение), поэтому у него тоже должен быть адрес в памяти. Тогда и 1024 получается lvalue.

М>Нет, число кладется в обычную секцию данных, а не в ro (если не обьявите как const)


Да никуда оно не кладётся.
Re[7]: Почему строка это lvalue, а число это rvalue?
От: Михaил  
Дата: 02.09.18 06:40
Оценка:
Здравствуйте, σ, Вы писали:

МР>>>Так число 1024 компилятор ведь тоже кладет в память (только на чтение), поэтому у него тоже должен быть адрес в памяти. Тогда и 1024 получается lvalue.


М>>Нет, число кладется в обычную секцию данных, а не в ro (если не обьявите как const)


σ>Да никуда оно не кладётся.


Зависит от настроек оптимизации и места, где объявлена переменная (если внутри функции — тогда, понятно, она будет на стеке а не в секции данных, только если это не константа, а вот если глобальная, то...) , и т п).

Скомпилируйте след. код с отключенным оптимизатором и посмотрите в дизассемблере:

int a=10;
const int b=15;
int main() {
cout << a << b;
}
Отредактировано 02.09.2018 6:43 Михaил . Предыдущая версия . Еще …
Отредактировано 02.09.2018 6:42 Михaил . Предыдущая версия .
Re[8]: Почему строка это lvalue, а число это rvalue?
От: σ  
Дата: 02.09.18 06:46
Оценка: +1
МР>>>>Так число 1024 компилятор ведь тоже кладет в память (только на чтение), поэтому у него тоже должен быть адрес в памяти. Тогда и 1024 получается lvalue.

М>>>Нет, число кладется в обычную секцию данных, а не в ro (если не обьявите как const)


σ>>Да никуда оно не кладётся.


М>Зависит от настроек оптимизации и места, где объявлена переменная


При чём тут переменная? Речь шла про литералы.
Переменные пусть кладутся куда хотят.
Re: Почему строка это lvalue, а число это rvalue?
От: Михaил  
Дата: 02.09.18 06:54
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Привет!


МР>

МР>int main() {
МР>   cout << "1024" << endl; // "1024" - lvalue?
МР>   cout << 1024 << endl;   // 1024 - rvalue?
МР>}

МР>


https://stackoverflow.com/questions/10004511/why-are-string-literals-l-value-while-all-other-literals-are-r-value
Re[8]: Почему строка это lvalue, а число это rvalue?
От: pagid Россия  
Дата: 03.09.18 06:40
Оценка: +2
Здравствуйте, Михaил, Вы писали:

М>Зависит от настроек оптимизации и места, где объявлена переменная (если внутри функции — тогда, понятно, она будет на стеке а не в секции данных, только если это не константа, а вот если глобальная, то...) , и т п).

М>Скомпилируйте след. код с отключенным оптимизатором и посмотрите в дизассемблере:

От целевой архитектуры зависит. С немалой вероятностью числовые константы будут частью машинных команд, а не лежать сегменте данных.
Re[2]: Почему строка это lvalue, а число это rvalue?
От: B0FEE664  
Дата: 03.09.18 08:24
Оценка:
Здравствуйте, σ, Вы писали:

σ>Потому что тут сказано так http://eel.is/c++draft/expr.prim.literal



Забавно, что gcc считает, что строка — это не lvalue:
#include <iostream>

int main() 
{
  const char* p = ++"asdf";
  std::cout << "ok\n";
  return 0;
}

compilation info

prog.cpp: In function ‘int main()’:
prog.cpp:6:21: error: increment of read-only location ‘(const char*)"asdf"’
   const char* p = ++"asdf";
                     ^~~~~~
prog.cpp:6:21: error: lvalue required as increment operand

проверка
И каждый день — без права на ошибку...
Re[3]: Почему строка это lvalue, а число это rvalue?
От: σ  
Дата: 03.09.18 09:13
Оценка:
BFE>Забавно, что gcc считает, что строка — это не lvalue:
BFE>
BFE>#include <iostream>

BFE>int main() 
BFE>{
BFE>  const char* p = ++"asdf";
BFE>  std::cout << "ok\n";
BFE>  return 0;
BFE>}
BFE>

BFE>
BFE>compilation info

BFE>prog.cpp: In function ‘int main()’:
BFE>prog.cpp:6:21: error: increment of read-only location ‘(const char*)"asdf"’
BFE>   const char* p = ++"asdf";
BFE>                     ^~~~~~
BFE>prog.cpp:6:21: error: lvalue required as increment operand
BFE>

BFE>проверка

По-моему, он считает, что ‘(const char*)"asdf"’ это не lvalue.
Если он обозначает так array-to-pointer conversion, то в принципе он прав в том, что это не lvalue.
С другой стороны, он не должен применять array-to-pointer conversion к аргументу ++.
Re[3]: Почему строка это lvalue, а число это rvalue?
От: uzhas Ниоткуда  
Дата: 03.09.18 09:27
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Забавно, что gcc считает, что строка — это не lvalue:


что-то текст ошибки не очень понятный
я бы предположил, что gcc считает, что указатель, полученный неявным приведением строкового литерала к const char*, не является lvalue
нельзя же применить ++ к массиву char, вот поэтому преобразование и происходит

однако смущает первая ошибка: prog.cpp:6:21: error: increment of read-only location ‘(const char*)"asdf"’
что за location и почему он read-only? мы же не пытаемся взять указатель на первую букву и записать туда другую букву...странно как-то
Re[4]: Почему строка это lvalue, а число это rvalue?
От: uzhas Ниоткуда  
Дата: 03.09.18 09:47
Оценка:
Здравствуйте, σ, Вы писали:

σ>С другой стороны, он не должен применять array-to-pointer conversion к аргументу ++.


а как иначе?

8.5.2.2 Increment and decrement [expr.pre.incr]
1 The operand of prefix ++ is modified by adding 1. The operand shall be a modifiable lvalue. The type of the
operand shall be an arithmetic type other than cv bool, or a pointer to a completely-defined object type. The
result is the updated operand; it is an lvalue, and it is a bit-field if the operand is a bit-field. The expression
++x is equivalent to x+=1.


вполне разумно здесь иметь неявную конвертацию к указателю
Re[5]: Почему строка это lvalue, а число это rvalue?
От: σ  
Дата: 03.09.18 13:21
Оценка: +1
σ>>С другой стороны, он не должен применять array-to-pointer conversion к аргументу ++.

U>а как иначе?


U>

U>8.5.2.2 Increment and decrement [expr.pre.incr]
U>1 The operand of prefix ++ is modified by adding 1. The operand shall be a modifiable lvalue. The type of the
U>operand shall be an arithmetic type other than cv bool, or a pointer to a completely-defined object type. The
U>result is the updated operand; it is an lvalue, and it is a bit-field if the operand is a bit-field. The expression
U>++x is equivalent to x+=1.


U>вполне разумно здесь иметь неявную конвертацию к указателю


[basic.lval]/6: Whenever a glvalue appears as an operand of an operator that expects a prvalue for that operand, the lvalue-to-rvalue, array-to-pointer, or function-to-pointer standard conversions are applied to convert the expression to a prvalue.

Строковый литерал это lvalue.
Оператор требует lvalue-операнд.

Разумно это НЕ иметь конвертацию к prvalue.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.