Что происходит, когда у кастового указателя есть оператор инкремента?
Например:
int x[100];
void *p;
x[0] = 0x12345678;
x[1] = 0xfacecafe;
x[3] = 0xdeadbeef;
p = x;
((int *) p) ++ ;
printf("The value = 0x%08x", *(int*)p);
Компиляция выше генерирует требуемую ошибку lvalue в строке с оператором ++.
Ответы
Ответ 1
Приведение создает временный указатель типа int *
. Вы не можете увеличивать время, поскольку оно не обозначает место для хранения результата.
В C и С++ standardese (int *)p
является rvalue, что примерно означает выражение, которое может появляться только в правой части присваивания.
p
, с другой стороны, это lvalue, что означает, что он может корректно отображаться в левой части задания. Только lvalues могут быть увеличены.
Ответ 2
Выражение ((int *) p)
рассматривает указатель, хранящийся внутри переменной p
, является указателем на int. Если вы хотите обработать эту переменную как указатель на переменную int (а затем увеличьте ее), используйте ссылку:
((int *&) p) ++ ;
Ответ 3
Вы можете получить ожидаемый результат с помощью
p = (int*)p + 1;
Использование оператора инкремента по разыменованному указателю на p
, который является lvalue, также работает:
(*(int**)&p)++;
Однако последнее не переносимо, поскольку (void*)p
может не иметь того же представления, что и (int*)p
.
Ответ 4
Благодаря larsmans для указания в правильном направлении.
Я позволил себе углубиться в это. Поэтому для дальнейшего использования в соответствии с разделами 6.5.2.4 и 6.5.4 стандарта C99 (http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf):
6.5.2.4 Операторы приращения и уменьшения постфикса
Ограничения
Операнд приращения postfix или декремент должен иметь квалифицированных или неквалифицированных реальных или тип указателя и должен быть модифицируемым именующее
..
..
6.5.4 Операторы роли
..
..
[Сноска] 89) Литой не дает lvalue. Таким образом, литой к квалифицированному типу эффект как приведение к неквалифицированному версии типа.
Примечание. Это относится только к C. С++ может обрабатывать отливки по-разному.
Ответ 5
выражение Rvalue ((int *) p)
создает и временное значение типа int*
, при котором оператор ++
не может быть применен.
++
требуется lvalue как его операнд.
Поскольку @FredOverflow упоминает lvalues
и rvalues
, очень мало связано с назначением.
Массивы - это lvalues, но они не могут быть назначены, потому что они не изменяемы.
std::string("Prasoon")
- выражение rvalue, которое все же может иметь место в левой части оператора присваивания, потому что нам разрешено вызывать функции-члены (operator =
в этом случае) во временных рядах.