Почему множественные приращения / убывания действительны в C ++, но не в C?

тест. (с / 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)-- операция? У кого-нибудь есть понимание этого?

6

Решение

В C результат префиксных и постфиксных операторов увеличения / уменьшения не является lvalue.

В C ++ результат оператора увеличения / уменьшения постфикса также не является lvalue, но результатом оператора увеличения / уменьшения префикса является lvalue.

Сейчас занимаюсь чем-то вроде (++a)-- в C ++ неопределенное поведение, потому что вы изменяете значение объекта дважды между двумя точками последовательности.

РЕДАКТИРОВАТЬ: продолжение комментария @ bames53. Это неопределенное поведение в C ++ 98 / C ++ 03, но изменения в C ++ 11 по идее точек последовательности теперь определяют это выражение.

13

Другие решения

В C и C ++ есть выражения lvalue, которые могут использоваться в левой части = выражения оператора и rvalue, которые не могут. C ++ позволяет большему количеству вещей быть lvalues, потому что он поддерживает семантику ссылок.

++ a = 3; /* makes sense in C++ but not in C. */

Операторы увеличения и уменьшения аналогичны операторам присваивания, поскольку они изменяют свой аргумент.

В C ++ 03 (++a)-- приведет к неопределенному поведению, потому что две операции, которые не упорядочены друг относительно друга, изменяют одну и ту же переменную. (Даже если кто-то «до» и один «пост», они не упорядочены, потому что нет ,, &&, ?или такой.)

В C ++ 11 выражение теперь делает то, что вы ожидаете. Но C11 не меняет таких правил, это синтаксическая ошибка.

3

Для тех, кто хочет получить точную информацию о различиях, как указано в стандартах, C99, §6.5.3 / 2, гласит:

Значение операнда оператора префикса ++ увеличивается. Результатом является новый
значение операнда после увеличения.

Напротив, C ++ 11, §5.3.2 / 1 говорит:

Результат обновлен операнд; это именующий, и это битовое поле, если
операнд является битовым полем.

[Акцент добавлен, в обоих случаях]

Также обратите внимание, что хотя (++a)-- дает неопределенное поведение (по крайней мере, в C ++ 03), когда a является int, если a некоторый пользовательский тип, так что вы используете свои собственные перегрузки ++ а также --, поведение будет определено — в таком случае вы получите эквивалент:

a.operator++().operator--(0);

Поскольку каждый оператор приводит к вызову функции (которая не может перекрываться), вы на самом деле делать иметь точки последовательности для принудительного определения определенного поведения (обратите внимание, что я не рекомендую его использовать, только отмечая, что поведение в действительности определено в этом случае).

2

§5.2.7 Увеличение и уменьшение:

Ценность постффикса ++ выражение — это значение его операнда. […]  Операнд должен быть изменяемым значением.

Ошибка, которую вы получаете в своей компиляции C, позволяет предположить, что это только особенность, присутствующая в C ++.

0
По вопросам рекламы [email protected]