Невозможно использовать оператор ++, - для результата из арифметики указателя - PullRequest
1 голос
/ 13 марта 2020

Я использую VS Code и G CC компилятор. Вот код:

#include <stdio.h>
#include <stdlib.h>    

int main()
{
    void *ptr = malloc(100);    

    printf("%p\n", ptr);               
    printf("%p\n", (int *)ptr + 1);    
    printf("%p\n", (int *)ptr - 1);    

    void *ptr2 = ptr; 

    printf("%p\n", (int *)ptr2 + 1);  // Works well

    printf("%p\n", ++(int *)ptr2);    // error: lvalue required as decrement operand



    free(ptr);

    return 0;
}

Когда я компилирую код выше, ++(int *)ptr2 получает ошибку: «lvalue требуется как операнд декремента».

Однако, (int *)ptr2 + 1 работает. Кто-нибудь может объяснить, почему это происходит?

Ответы [ 3 ]

3 голосов
/ 13 марта 2020

Результат приведения не является lvalue. В разделе 6.5.4 Cast operators ISO C11 есть сноска, в которой говорится:

Приведение не дает lvalue. Таким образом, приведение к квалифицированному типу имеет тот же эффект, что и приведение к неквалифицированной версии этого типа.

Аналогично, в 6.5.3.1 Prefix increment and decrement operators говорится (мой акцент):

Операнд префиксного оператора увеличения или уменьшения должен иметь атом c, квалифицированный или неквалифицированный вещественный или указательный тип и должен быть изменяемым lvalue.

Следовательно, то, что вы пытаетесь сделать, недопустимо.

Причина, по которой (int *)ptr2 + 1 работает, заключается в том, что ptr2 является lvalue, поэтому оно может быть бросать. Добавление 1 делается к значению приведения, и это также допустимо.

Ситуация, которую вы пытаетесь, ничем не отличается от ++(ptr+1), который является другим способом. попытки увеличить ненулевое значение. Это потому, что и ваше приведение, и выражение ptr+1 являются эфемерными объектами, которые должны существовать достаточно долго, чтобы их можно было использовать для немедленной операции (дополнение или приведение, не до -нкремент).

Ваша проблема исчезнет, ​​если вы слегка переделаете способ выполнения задач (поскольку void* свободно приводит к большинству других указателей):

printf("%p\n", ptr2 = ((int*)ptr2) + 1);
0 голосов
/ 13 марта 2020

++ работает на lvalue. Другими словами, ++something по существу означает something = something + 1. Таким образом, вы в основном пытаетесь присвоить значение литералу, что недопустимо. С другой стороны, something + 1 - это просто выражение, которое подлежит оценке и обрабатывается в соответствии с контекстом.

0 голосов
/ 13 марта 2020

Оператору ++ требуется lvalue в качестве операнда, и его побочным эффектом является обновление значения, хранящегося в ячейке памяти, обозначенной значением.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...