Что происходит, когда приведенный указатель имеет оператор приращения? - PullRequest
13 голосов
/ 20 марта 2011

Например:

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 в строке с оператором ++.

Ответы [ 5 ]

18 голосов
/ 20 марта 2011

Приведение создает временный указатель типа int *. Вы не можете увеличить временное значение, так как оно не обозначает место для сохранения результата.

В стандартах C и C ++ (int *)p - это r-значение , что примерно означает выражение, которое может встречаться только в правой части присваивания.

p с другой стороны - это lvalue , что означает, что он может корректно отображаться в левой части назначения. Только l-значения могут быть увеличены.

3 голосов
/ 20 марта 2011

Выражение ((int *) p) обрабатывает указатель, хранящийся в переменной p, это указатель на int. Если вы хотите обрабатывать переменную как указатель на переменную int (а затем увеличивать ее), используйте приведение ссылки:

((int *&) p) ++ ;
1 голос
/ 21 марта 2011

Спасибо Ларсману за указание в правильном направлении.

Я позволил себе углубиться в это.Поэтому для дальнейшего использования в соответствии с разделами 6.5.2.4 и 6.5.4 стандарта C99 (http://www.open -std.org / jtc1 / sc22 / WG14 / www / docs / n1256.pdf):

6.5.2.4 Операторы приращения и уменьшения постфикса

Ограничения

Операнд оператора приращения или уменьшения постфикса должен иметь квалифицированный или неквалифицированный вещественный или указательный тип и быть модифицируемым значением lvalue....6.5.4 Операторы приведения....[Сноска] 89) Применение не дает lvalue.Таким образом, приведение к квалифицированному типу имеет тот же эффект, что и приведение к неквалифицированной версии типа.

Примечание. Это относится только к C. C ++ может обрабатывать приведение по-разному.

1 голос
/ 20 марта 2011

Вы можете получить желаемый результат с помощью

p = (int*)p + 1;

Использование оператора приращения для разыменованного указателя на p, который является lvalue, также работает:

(*(int**)&p)++;

Однако последний не является переносимым, поскольку (void*)p может не иметь такого представления, как (int*)p.

0 голосов
/ 20 марта 2011

Rvalue выражение ((int *) p) создает и временный тип int*, к которому нельзя применить оператор ++.

++ требует lvalue в качестве операнда.

As @FredOverflow упоминает, что lvalues и rvalues имеют очень мало общего с присваиванием.

Массивы являются lvalue, но им нельзя присваивать, потому что они не модифицируемы.std::string("Prasoon") является выражением rvalue, однако оно может встречаться слева от оператора присваивания, поскольку нам разрешено вызывать функции-члены (в данном случае operator =) для временных значений.

...