тест. (с / CPP)
#include <stdio.h>
int main(int argc, char** argv)
{
int a = 0, b = 0;
printf("a = %d, b = %d\n", a, b);
b = (++a)--;
printf("a = %d, b = %d\n", a, b);
return 0;
}
Если я сохраню вышеупомянутое как файл .cpp, он компилирует и выводит это после выполнения:
a = 0, b = 0
a = 0, b = 1
Однако, если я сохраняю его как файл .c, я получаю следующую ошибку:
test.c:7:12: error: lvalue required as decrement operator.
Не должен (++a)
операция должна быть решена до (newValue)--
операция? У кого-нибудь есть понимание этого?
В C результат префиксных и постфиксных операторов увеличения / уменьшения не является lvalue.
В C ++ результат оператора увеличения / уменьшения постфикса также не является lvalue, но результатом оператора увеличения / уменьшения префикса является lvalue.
Сейчас занимаюсь чем-то вроде (++a)--
в C ++ неопределенное поведение, потому что вы изменяете значение объекта дважды между двумя точками последовательности.
РЕДАКТИРОВАТЬ: продолжение комментария @ bames53. Это неопределенное поведение в C ++ 98 / C ++ 03, но изменения в C ++ 11 по идее точек последовательности теперь определяют это выражение.
В C и C ++ есть выражения lvalue, которые могут использоваться в левой части =
выражения оператора и rvalue, которые не могут. C ++ позволяет большему количеству вещей быть lvalues, потому что он поддерживает семантику ссылок.
++ a = 3; /* makes sense in C++ but not in C. */
Операторы увеличения и уменьшения аналогичны операторам присваивания, поскольку они изменяют свой аргумент.
В C ++ 03 (++a)--
приведет к неопределенному поведению, потому что две операции, которые не упорядочены друг относительно друга, изменяют одну и ту же переменную. (Даже если кто-то «до» и один «пост», они не упорядочены, потому что нет ,
, &&
, ?
или такой.)
В C ++ 11 выражение теперь делает то, что вы ожидаете. Но C11 не меняет таких правил, это синтаксическая ошибка.
Для тех, кто хочет получить точную информацию о различиях, как указано в стандартах, C99, §6.5.3 / 2, гласит:
Значение операнда оператора префикса ++ увеличивается. Результатом является новый
значение операнда после увеличения.
Напротив, C ++ 11, §5.3.2 / 1 говорит:
[Акцент добавлен, в обоих случаях]Результат обновлен операнд; это именующий, и это битовое поле, если
операнд является битовым полем.
Также обратите внимание, что хотя (++a)--
дает неопределенное поведение (по крайней мере, в C ++ 03), когда a
является int
, если a
некоторый пользовательский тип, так что вы используете свои собственные перегрузки ++
а также --
, поведение будет определено — в таком случае вы получите эквивалент:
a.operator++().operator--(0);
Поскольку каждый оператор приводит к вызову функции (которая не может перекрываться), вы на самом деле делать иметь точки последовательности для принудительного определения определенного поведения (обратите внимание, что я не рекомендую его использовать, только отмечая, что поведение в действительности определено в этом случае).
§5.2.7 Увеличение и уменьшение:
Ценность постффикса
++
выражение — это значение его операнда. […] Операнд должен быть изменяемым значением.
Ошибка, которую вы получаете в своей компиляции C, позволяет предположить, что это только особенность, присутствующая в C ++.