Почему в C не работают несколько операторов декремента, когда они работают на С++?

Посмотрите на этот вопрос и попробуйте код:

int x = 100;

while ( 0 <-------------------- x )
{
    printf("%d ", x);
}

Я попытался скомпилировать с gcc и получил следующую ошибку:

file.c: In function 'main':
file:c:10:27: error: lvalue required as decrement operand
 while ( 0 <-------------------- x )

Но компиляция с помощью g++ работает. Почему этот код действителен в С++, но не C?

Ответ 1

В C, --x - значение, а не lvalue. Его эффект заключается в уменьшении x и вычислении на вновь присвоенное значение x. Поскольку --x не является lvalue, его нельзя уменьшить.

В С++ --x - это значение lvalue, а не rvalue. Его эффект заключается в уменьшении x и оценивании до x как lvalue. Поскольку --x снова является lvalue, его можно снова уменьшить.

Причина, по которой смысл --x имеет значение lvalue в С++, состоит в том, что С++ вводил ссылочные типы. Учитывая,

void f(int &);
int i;

может возникнуть смысл вызвать f(--i), который передает i по ссылке после его уменьшения.

Так как C не имеет ссылочных типов, то небольшая точка в --i является lvalue. Исторически это никогда не было, и в отличие от С++, C никогда не получал убедительных оснований для изменения правил.

Обратите внимание, что С++ требует более обширных изменений, чем создание --x lvalue, чтобы фактически позволить ему работать. Создание --x lvalue, без чего-либо другого, приведет к поведению --x undefined, потому что между модификацией и x и последующим преобразованием lvalue-to-value не будет точки последовательности. Еще более ясно это для ----x. С++ должен был изменить правила последовательности, чтобы заставить его работать. В C изменения правил последовательности могут привести к тому, что существующие компиляторы будут соответствовать новым правилам, поэтому такие модификации, вероятно, будут отвергнуты, если не будет большой выгоды.