Join the Stack Overflow Community
Stack Overflow is a community of 6.7 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

Looking at this question and trying out some of the code:

int x = 100;

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

I attempted to compile with gcc and got the following error:

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

But compiling with g++ works. Why is this code valid in C++ but not C?

share|improve this question
36  
Because C and C++ are two different languages. In other words, C and C++ are not the same language. – Kerrek SB 12 hours ago
3  
@chqrlie Circular reasoning. Q: Why does water come out of my tap and not Pepsi? A: Because taps can be used to easily access water. – immibis 11 hours ago
3  
In C, you can work around it by writing while (0 < (x -= 10)). – dan04 11 hours ago
11  
Alternately, to keep the fancy style of the OP, while (0 < (x +=-+-+- 10)) – chqrlie 11 hours ago
1  
The thread you posted needs a big sign with sarcasm/irony/humor above it, most things there are not to be used. I would consider @dan04 's style while (0 < (x -= 10)) superior in any way.... Just because things are possible doesn't mean they are good. – Kami Kaze 3 hours ago
up vote 46 down vote accepted

In C, --x is a value, not an lvalue. Its effect is to decrement x, and evaluate to the newly assigned value of x. Since --x is not an lvalue, it cannot be decremented.

In C++, --x is an lvalue, not an rvalue. Its effect is to decrement x, and evaluate to x as an lvalue. Since --x is an lvalue again, it can be decremented again.

The reason why it makes sense for --x to be an lvalue in C++ is because C++ introduced reference types. Given

void f(int &);
int i;

it may make sense to call f(--i), which passes i by reference after decrementing it.

Since C doesn't have reference types, there's little point in --i being an lvalue. Historically, it never was, and unlike C++, C never gained a compelling reason to change the rules.

Note that C++ required more extensive changes than making --x an lvalue to actually let it work. Making --x an lvalue, without anything else, would make --x undefined behaviour, because there would not be a sequence point between the modification to x and the subsequent lvalue-to-value conversion. Even more clearly so for ----x. C++ had to modify the sequencing rules to make it work. In C, modifications to the sequencing rules might cause problems for existing compilers to conform to the new rules, so such modifications would likely be rejected unless there's a big benefit.

share|improve this answer
6  
You could still want to say something like f(&--x). I'm not sure I buy your reason why "there's no point" in C. – Kerrek SB 12 hours ago
1  
@KerrekSB Fair point, but there's still little point. I'd say f(&--x) is less likely to be what someone actually wants to write than f(--x). Regardless, C also has a problem that changes to the rules would be problematic for existing implementations, I added a bit on that. – hvd 12 hours ago
    
C++ did not require any sequencing changes to make --x an lvalue. The pre-C++11 rule about sequence points pertains to reads and writes, not to lvalue-to-rvalue conversions. – M.M 10 hours ago
3  
The behaviour of ----x changed in C++11 (well-defined after, undefined before) – M.M 9 hours ago
3  
If you really want to do f(&--x) in C, you can do f((--x,&x)). – G-Man 8 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.