Здравствуйте, Максим Рогожин, Вы писали:
МР>Объяснить это как-то можно?
Возможно, потому, что строковый литерал имеет адрес в памяти, значит, формально, туда можно что-то присвоить. Хотя в плюсах компилятор может положить (и обычно кладёт) эти литералы в память только на чтение. Например, ((char *) "abc") [0] = 'd'; синтаксически правильно, хотя и UB.
А как Вы это выяснили и на что это влияет?
Re[4]: Почему строка это lvalue, а число это rvalue?
Здравствуйте, cures, Вы писали:
C>Возможно, потому, что строковый литерал имеет адрес в памяти, значит, формально, туда можно что-то присвоить. Хотя в плюсах компилятор может положить (и обычно кладёт) эти литералы в память только на чтение. Например, ((char *) "abc") [0] = 'd'; синтаксически правильно, хотя и UB.
Так число 1024 компилятор ведь тоже кладет в память (только на чтение), поэтому у него тоже должен быть адрес в памяти. Тогда и 1024 получается lvalue.
C>А как Вы это выяснили и на что это влияет?
Да прочитал в статье какой-то. На что может повлиять сам бы хотел знать.
Re[5]: Почему строка это lvalue, а число это rvalue?
Здравствуйте, Максим Рогожин, Вы писали:
МР>Так число 1024 компилятор ведь тоже кладет в память (только на чтение), поэтому у него тоже должен быть адрес в памяти. Тогда и 1024 получается lvalue.
Не факт. Число может быть в регистре и адреса не иметь (т.к. rvalue). Возможно, т.к. строка — это массив, её решили сделать lvalue, т.к. она всегда в памяти и имеет адрес (это догадка, на самом деле не знаю).
Re[5]: Почему строка это lvalue, а число это rvalue?
Здравствуйте, Максим Рогожин, Вы писали:
МР>Так число 1024 компилятор ведь тоже кладет в память (только на чтение), поэтому у него тоже должен быть адрес в памяти. Тогда и 1024 получается lvalue.
Нет, число кладется в обычную секцию данных, а не в ro (если не обьявите как const)
А строки кладутся в ro data, потому что они константные по умолчанию (так и называются — “string constant”.
C>>А как Вы это выяснили и на что это влияет? МР>Да прочитал в статье какой-то. На что может повлиять сам бы хотел знать.
МР>>Так число 1024 компилятор ведь тоже кладет в память (только на чтение), поэтому у него тоже должен быть адрес в памяти. Тогда и 1024 получается lvalue.
М>Нет, число кладется в обычную секцию данных, а не в ro (если не обьявите как const)
Да никуда оно не кладётся.
Re[7]: Почему строка это lvalue, а число это rvalue?
Здравствуйте, σ, Вы писали:
МР>>>Так число 1024 компилятор ведь тоже кладет в память (только на чтение), поэтому у него тоже должен быть адрес в памяти. Тогда и 1024 получается lvalue.
М>>Нет, число кладется в обычную секцию данных, а не в ro (если не обьявите как const)
σ>Да никуда оно не кладётся.
Зависит от настроек оптимизации и места, где объявлена переменная (если внутри функции — тогда, понятно, она будет на стеке а не в секции данных, только если это не константа, а вот если глобальная, то...) , и т п).
Скомпилируйте след. код с отключенным оптимизатором и посмотрите в дизассемблере:
int a=10;
const int b=15;
int main() {
cout << a << b;
}
МР>>>>Так число 1024 компилятор ведь тоже кладет в память (только на чтение), поэтому у него тоже должен быть адрес в памяти. Тогда и 1024 получается lvalue.
М>>>Нет, число кладется в обычную секцию данных, а не в ro (если не обьявите как const)
σ>>Да никуда оно не кладётся.
М>Зависит от настроек оптимизации и места, где объявлена переменная
При чём тут переменная? Речь шла про литералы.
Переменные пусть кладутся куда хотят.
Здравствуйте, Михaил, Вы писали:
М>Зависит от настроек оптимизации и места, где объявлена переменная (если внутри функции — тогда, понятно, она будет на стеке а не в секции данных, только если это не константа, а вот если глобальная, то...) , и т п). М>Скомпилируйте след. код с отключенным оптимизатором и посмотрите в дизассемблере:
От целевой архитектуры зависит. С немалой вероятностью числовые константы будут частью машинных команд, а не лежать сегменте данных.
Re[2]: Почему строка это lvalue, а число это rvalue?
Забавно, что 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
По-моему, он считает, что ‘(const char*)"asdf"’ это не lvalue.
Если он обозначает так array-to-pointer conversion, то в принципе он прав в том, что это не lvalue.
С другой стороны, он не должен применять array-to-pointer conversion к аргументу ++.
Re[3]: Почему строка это lvalue, а число это rvalue?
Здравствуйте, 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?
Здравствуйте, σ, Вы писали:
σ>С другой стороны, он не должен применять 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?
σ>>С другой стороны, он не должен применять 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-операнд.