Выражение должно быть допустимо для изменения левосторонним значением
PVOID trampoline = (PVOID )1; //для примера присвоил рандомное значение
((PBYTE)trampoline)++; //тут ошибка (Выражение должно быть допустимо для изменения левосторонним значением)
Почему такая ошибка, ведь мы сначала преобразовали наш указатель к указателю на BYTE, после чего инкрементируем? Причем в чисто сишном компиляторе все нормально компилируется.
Ответы (1 шт):
стандарт :
7.6.3 Explicit type conversion (cast notation)
The result of the expression (T) cast-expression is of type T. The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type and an xvalue if T is an rvalue reference to object type; otherwise the result is a prvalue. [Note 1 : If T is a non-class type that is cv-qualified, the cv-qualifier s are discarded when determining the type of the resulting prvalue; see 7.2. — end note]
перевод :
7.6.3 Явное преобразование типов (приведенная нотация)
Результат приведения выражения (T) имеет тип T. Результатом является значение lvalue, если T является типом ссылки lvalue или ссылкой rvalue на тип функции, и значение xvalue, если T является ссылкой rvalue на тип объекта; в противном случае результатом является значение prvalue. [Примечание 1 : Если T-тип, не относящийся к классу, который квалифицируется cv, квалификатор s cv отбрасывается при определении типа результирующего значения prvalue; см. 7.2. — конец примечания]
Приведение на объект даёт новый временный объект. Временный объект это не lvalue. А ссылка или (*ptr) будет lvalue после приведения типа. И её можно будет менять.
# include <cstdint>
# include <iostream>
typedef void * PVOID ;
typedef uint8_t * PBYTE ;
typedef uint8_t BYTE ;
BYTE arr[]={0,0,0};
PVOID trampoline = (PVOID )(&arr[0]);
int main(){
// тут была ошибка (Выражение должно быть допустимо для изменения левосторонним значением)
PBYTE && tmp = ((PBYTE)trampoline);
tmp ++ ;
std::cout<<"trampoline = "<<trampoline<<std::endl;
std::cout<<"tmp = "<<(void*)tmp<<std::endl;
(*(PBYTE*)&trampoline)++;
std::cout<<"trampoline = "<<trampoline<<std::endl;
((PBYTE&)trampoline)++;
std::cout<<"trampoline = "<<trampoline<<std::endl;
}
=>
trampoline = 0x404191
tmp = 0x404192
trampoline = 0x404192
trampoline = 0x404193
Справочник по Left-value Right-value :
variable = LValue
& variable = RValue
(* (any pointer)) = LValue
((T)(any value)) = RValue
(*(T*)(any pointer)) = LValue
((T&)(any link)) - LValue