Why doesn't c = a+++++b work in C? [duplicate] - c

int main ()
{
int a = 5,b = 2;
printf("%d",a+++++b);
return 0;
}
This code gives the following error:
error: lvalue required as increment operand
But if I put spaces throughout a++ + and ++b, then it works fine.
int main ()
{
int a = 5,b = 2;
printf("%d",a++ + ++b);
return 0;
}
What does the error mean in the first example?

Compilers are written in stages. The first stage is called the lexer and turns characters into a symbolic structure. So "++" becomes something like an enum SYMBOL_PLUSPLUS. Later, the parser stage turns this into an abstract syntax tree, but it can't change the symbols. You can affect the lexer by inserting spaces (which end symbols unless they are in quotes).
Normal lexers are greedy (with some exceptions), so your code is being interpreted as
a++ ++ +b
The input to the parser is a stream of symbols, so your code would be something like:
[ SYMBOL_NAME(name = "a"),
SYMBOL_PLUS_PLUS,
SYMBOL_PLUS_PLUS,
SYMBOL_PLUS,
SYMBOL_NAME(name = "b")
]
Which the parser thinks is syntactically incorrect. (EDIT based on comments: Semantically incorrect because you cannot apply ++ to an r-value, which a++ results in)
a+++b
is
a++ +b
Which is ok. So are your other examples.

printf("%d",a+++++b); is interpreted as (a++)++ + b according to the Maximal Munch Rule!.
++ (postfix) doesn't evaluate to an lvalue but it requires its operand to be an lvalue.
!
6.4/4 says
the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token"

The lexer uses what's generally called a "maximum munch" algorithm to create tokens. That means as it's reading characters in, it keeps reading characters until it encounters something that can't be part of the same token as what it already has (e.g., if it's been reading digits so what it has is a number, if it encounters an A, it knows that can't be part of the number. so it stops and leaves the A in the input buffer to use as the beginning of the next token). It then returns that token to the parser.
In this case, that means +++++ gets lexed as a ++ ++ + b. Since the first post-increment yields an rvalue, the second can't be applied to it, and the compiler gives an error.
Just FWIW, in C++ you can overload operator++ to yield an lvalue, which allows this to work. For example:
struct bad_code {
bad_code &operator++(int) {
return *this;
}
int operator+(bad_code const &other) {
return 1;
}
};
int main() {
bad_code a, b;
int c = a+++++b;
return 0;
}
The compiles and runs (though it does nothing) with the C++ compilers I have handy (VC++, g++, Comeau).

This exact example is covered in the draft C99 standard(same details in C11) section 6.4 Lexical elements paragraph 4 which in says:
If the input stream has been parsed into preprocessing tokens up to a
given character, the next preprocessing token is the longest sequence
of characters that could constitute a preprocessing token. [...]
which is also known as the maximal munch rule which is used in in lexical analysis to avoid ambiguities and works by taking as many elements as it can to form a valid token.
the paragraph also has two examples the second one is an exact match for you question and is as follows:
EXAMPLE 2 The program fragment x+++++y is parsed as x ++ ++ + y, which
violates a constraint on increment operators, even though the parse x
++ + ++ y might yield a correct expression.
which tells us that:
a+++++b
will be parsed as:
a ++ ++ + b
which violates the constraints on post increment since the result of the first post increment is an rvalue and post increment requires an lvalue. This is covered in section 6.5.2.4 Postfix increment and decrement operators which says (emphasis mine):
The operand of the postfix increment or decrement operator shall have
qualified or unqualified real or pointer type and shall be a
modifiable lvalue.
and
The result of the postfix ++ operator is the value of the operand.
The book C++ Gotchas also covers this case in Gotcha #17 Maximal Munch Problems it is the same problem in C++ as well and it also gives some examples. It explains that when dealing with the following set of characters:
->*
the lexical analyzer can do one of three things:
Treat it as three tokens: -, > and *
Treat it as two tokens: -> and *
Treat it as one token: ->*
The maximal munch rule allows it to avoid these ambiguities. The author points out that it (In the C++ context):
solves many more problems than it causes, but in two common
situations, it’s an annoyance.
The first example would be templates whose template arguments are also templates (which was solved in C++11), for example:
list<vector<string>> lovos; // error!
^^
Which interprets the closing angle brackets as the shift operator, and so a space is required to disambiguate:
list< vector<string> > lovos;
^
The second case involves default arguments for pointers, for example:
void process( const char *= 0 ); // error!
^^
would be interpreted as *= assignment operator, the solution in this case is to name the parameters in the declaration.

Your compiler desperately tries to parse a+++++b, and interprets it as (a++)++ +b. Now, the result of the post-increment (a++) is not an lvalue, i.e. it can't be post-incremented again.
Please don't ever write such code in production quality programs. Think about the poor fellow coming after you who needs to interpret your code.

(a++)++ +b
a++ returns the previous value, a rvalue. You can't increment this.

Because it causes undefined behaviour.
Which one is it?
c = (a++)++ + b
c = (a) + ++(++b)
c = (a++) + (++b)
Yeah, neither you nor the compiler know it.
EDIT:
The real reason is the one as said by the others:
It gets interpreted as (a++)++ + b.
but post increment requires a lvalue (which is a variable with a name) but (a++) returns a rvalue which cannot be incremented thus leading to the error message you get.
Thx to the others to pointing this out.

I think the compiler sees it as
c = ((a++)++)+b
++ has to have as an operand a value that can be modified. a is a value that can be modified. a++ however is an 'rvalue', it cannot be modified.
By the way the error I see on GCC C is the same, but differently-worded: lvalue required as increment operand.

Follow this precesion order
1.++ (pre increment)
2.+ -(addition or subtraction)
3."x"+ "y"add both the sequence
int a = 5,b = 2;
printf("%d",a++ + ++b); //a is 5 since it is post increment b is 3 pre increment
return 0; //it is 5+3=8

Related

Increment madness [duplicate]

int main ()
{
int a = 5,b = 2;
printf("%d",a+++++b);
return 0;
}
This code gives the following error:
error: lvalue required as increment operand
But if I put spaces throughout a++ + and ++b, then it works fine.
int main ()
{
int a = 5,b = 2;
printf("%d",a++ + ++b);
return 0;
}
What does the error mean in the first example?
Compilers are written in stages. The first stage is called the lexer and turns characters into a symbolic structure. So "++" becomes something like an enum SYMBOL_PLUSPLUS. Later, the parser stage turns this into an abstract syntax tree, but it can't change the symbols. You can affect the lexer by inserting spaces (which end symbols unless they are in quotes).
Normal lexers are greedy (with some exceptions), so your code is being interpreted as
a++ ++ +b
The input to the parser is a stream of symbols, so your code would be something like:
[ SYMBOL_NAME(name = "a"),
SYMBOL_PLUS_PLUS,
SYMBOL_PLUS_PLUS,
SYMBOL_PLUS,
SYMBOL_NAME(name = "b")
]
Which the parser thinks is syntactically incorrect. (EDIT based on comments: Semantically incorrect because you cannot apply ++ to an r-value, which a++ results in)
a+++b
is
a++ +b
Which is ok. So are your other examples.
printf("%d",a+++++b); is interpreted as (a++)++ + b according to the Maximal Munch Rule!.
++ (postfix) doesn't evaluate to an lvalue but it requires its operand to be an lvalue.
!
6.4/4 says
the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token"
The lexer uses what's generally called a "maximum munch" algorithm to create tokens. That means as it's reading characters in, it keeps reading characters until it encounters something that can't be part of the same token as what it already has (e.g., if it's been reading digits so what it has is a number, if it encounters an A, it knows that can't be part of the number. so it stops and leaves the A in the input buffer to use as the beginning of the next token). It then returns that token to the parser.
In this case, that means +++++ gets lexed as a ++ ++ + b. Since the first post-increment yields an rvalue, the second can't be applied to it, and the compiler gives an error.
Just FWIW, in C++ you can overload operator++ to yield an lvalue, which allows this to work. For example:
struct bad_code {
bad_code &operator++(int) {
return *this;
}
int operator+(bad_code const &other) {
return 1;
}
};
int main() {
bad_code a, b;
int c = a+++++b;
return 0;
}
The compiles and runs (though it does nothing) with the C++ compilers I have handy (VC++, g++, Comeau).
This exact example is covered in the draft C99 standard(same details in C11) section 6.4 Lexical elements paragraph 4 which in says:
If the input stream has been parsed into preprocessing tokens up to a
given character, the next preprocessing token is the longest sequence
of characters that could constitute a preprocessing token. [...]
which is also known as the maximal munch rule which is used in in lexical analysis to avoid ambiguities and works by taking as many elements as it can to form a valid token.
the paragraph also has two examples the second one is an exact match for you question and is as follows:
EXAMPLE 2 The program fragment x+++++y is parsed as x ++ ++ + y, which
violates a constraint on increment operators, even though the parse x
++ + ++ y might yield a correct expression.
which tells us that:
a+++++b
will be parsed as:
a ++ ++ + b
which violates the constraints on post increment since the result of the first post increment is an rvalue and post increment requires an lvalue. This is covered in section 6.5.2.4 Postfix increment and decrement operators which says (emphasis mine):
The operand of the postfix increment or decrement operator shall have
qualified or unqualified real or pointer type and shall be a
modifiable lvalue.
and
The result of the postfix ++ operator is the value of the operand.
The book C++ Gotchas also covers this case in Gotcha #17 Maximal Munch Problems it is the same problem in C++ as well and it also gives some examples. It explains that when dealing with the following set of characters:
->*
the lexical analyzer can do one of three things:
Treat it as three tokens: -, > and *
Treat it as two tokens: -> and *
Treat it as one token: ->*
The maximal munch rule allows it to avoid these ambiguities. The author points out that it (In the C++ context):
solves many more problems than it causes, but in two common
situations, it’s an annoyance.
The first example would be templates whose template arguments are also templates (which was solved in C++11), for example:
list<vector<string>> lovos; // error!
^^
Which interprets the closing angle brackets as the shift operator, and so a space is required to disambiguate:
list< vector<string> > lovos;
^
The second case involves default arguments for pointers, for example:
void process( const char *= 0 ); // error!
^^
would be interpreted as *= assignment operator, the solution in this case is to name the parameters in the declaration.
Your compiler desperately tries to parse a+++++b, and interprets it as (a++)++ +b. Now, the result of the post-increment (a++) is not an lvalue, i.e. it can't be post-incremented again.
Please don't ever write such code in production quality programs. Think about the poor fellow coming after you who needs to interpret your code.
(a++)++ +b
a++ returns the previous value, a rvalue. You can't increment this.
Because it causes undefined behaviour.
Which one is it?
c = (a++)++ + b
c = (a) + ++(++b)
c = (a++) + (++b)
Yeah, neither you nor the compiler know it.
EDIT:
The real reason is the one as said by the others:
It gets interpreted as (a++)++ + b.
but post increment requires a lvalue (which is a variable with a name) but (a++) returns a rvalue which cannot be incremented thus leading to the error message you get.
Thx to the others to pointing this out.
I think the compiler sees it as
c = ((a++)++)+b
++ has to have as an operand a value that can be modified. a is a value that can be modified. a++ however is an 'rvalue', it cannot be modified.
By the way the error I see on GCC C is the same, but differently-worded: lvalue required as increment operand.
Follow this precesion order
1.++ (pre increment)
2.+ -(addition or subtraction)
3."x"+ "y"add both the sequence
int a = 5,b = 2;
printf("%d",a++ + ++b); //a is 5 since it is post increment b is 3 pre increment
return 0; //it is 5+3=8

Is the order of evaluation with comma operator & assignment in C predictable?

Recently cppcheck raised an error in some C code, that has the structure:
((void)(value_prev = value), value = new_value())
In most cases this can be split onto 2 lines, however there are some cases this is useful to have in a single statement.
In practice I found this works with popular compilers (GCC/Clang/MSVC), which don't give any warnings (even with warning levels set to their highest).
Example code:
#include <stdio.h>
int get_next(int i);
int main() {
int i = 0, i_prev = 10;
do {
printf("%d\n", i);
} while ((void)(i_prev = i),
(i = get_next(i)) != 10);
}
CppCheck 1.73 (latest at time of writing) gives an error with this code:
(error) Expression '(void)(i_prev=i),(i=get_next(i))!=10'
depends on order of evaluation of side effects`
While the code could be changed to quiet the warning, is the order really undefined?
The order is defined, because there is a sequence point between them. See ISO/IEC 9899 6.5.17:
The left operand of a comma operator is evaluated as a void
expression; there is a sequence point after its evaluation. Then
the right operand is evaluated; the result has its type and value. 95)
If an attempt is made to modify the result of a comma operator or to
access it after the next sequence point, the behavior is undefined.
They then give an explicit example:
In the function call
f(a, (t=3, t+2), c)
the function has three
arguments, the second of which has the value 5.
I'm not entirely sure why CppCheck is flagging it.

Assigning multiple integers separated by comma to an int in C - Why does that work? What for? [duplicate]

This question already has answers here:
C comma operator
(4 answers)
What does the comma operator , do?
(8 answers)
Closed 7 years ago.
I saw this in an exam and when I tried it out I was surprised. I tried it online and it works too. So I think it is the C language.
Why is that working? What is the use case for such an assignment syntax?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int i = (1,2,3,4,5);
printf("%d", i);
return 0;
}
These are not "multiple integers", but a comma operator. The whole parenthesised part is a single expression with each sub-expression (separated by commas) evaluated strictly from left to right. The results of all but the rightmost subexpression are ignored. The result of the whole expression is that of the last (rightmost) expression. Here it is the integer value 5.
Note that this operator is mostly used where only a single expression is allowed to add further side-effects. E.g. in a loop like:
int cnt = 0;
for ( const char *cp = "Hello" ; *cp != '\0' ; cp++, cnt++ ) ;
This counts the number of characters in a C-string, incrementing the pointer and cnt after each iteration. The results are ignored here.
So, this is in no way related to tuples or similar like in Python. There are actually no cases the usage of this operator is unavoidable and it should be used with caution — and some coding standards forbid its usage.
That's the comma operator at work. It evaluates the expression on its left-hand side, creates a sequence point, discards the value of the expression, then evaluates the expression on the right-hand side, and returns that as the value. When there are multiple expressions as in the example, then each is evaluated in turn and only the last is kept. With the sample, the compiler does the evaluation because every value is known at compile time. Note that the argument list to a function is not a use of the comma operator.
That isn't a valid use-case for the comma operator. What might be a more nearly valid use-case would be some operations with side-effects (such as function calls) that need to be sequenced and the final value assigned:
int i = (getchar(), getchar(), getchar());
This sets i to the third character in standard input, or EOF if there are not three characters left in the standard input to be read. Still not a realistic use-case, but better than assigning a list of constants.
In addition to the other answers, you need to watch for instances where a , is the comma operator as opposed to when it is a separator. For example, the following is invalid:
int i = 1,2,3,4,5;
In this case, the , is a separator between variable declarations. It declares i as an int and initializes it to 1, then it attempts to parse 2 as a variable name, which fails.
It works because you're using the "comma operator", which evaluates the subexpressions on the left and right, and has the value from the right-hand expression.
So in (1,2,3,4,5), 1 is evaluated and the result is discarded, then 2,3,4,5... in which (because of the next comma) 2 is evaluated and the result discarded, then 3,4,5... in which 3 is evaluated and discarded, then 4,5... in which 4 is evaluated and discarded, then 5 which becomes the result of the expression.
As for when it's useful, mainly as a shortcut when you need to evaluate several (sub)expressions for their side effects but aren't interested in their values (except maybe the last one). It's sometimes convenient in for loop expressions, such as when incrementing two variables:
for (i=0,j=1; j < len; i++,j++) {
..where it appears in both the initialization expression and the loop expression.
Why is that working?
Because its a valid C syntax. The comma in (1,2,3,4,5) are comma operator
C11: 6.5.17 Comma operator
Syntax
1 expression:
assignment-expression
expression , assignment-expression
Semantics
2 The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value.114)
What is the use case for such an assignment syntax?
See the example below
3 EXAMPLE As indicated by the syntax, the comma operator (as described in this subclause) cannot appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists of initializers). On the other hand, it can be used within a parenthesized expression or within the second
expression of a conditional operator in such contexts. In the function call
f(a, (t=3, t+2), c)
the function has three arguments, the second of which has the value 5.

Why compiler treats i+++++i and i+++i differently [duplicate]

This question already has answers here:
Why doesn't a+++++b work?
(9 answers)
Closed 9 years ago.
int i=5;
printf("%d",i+++++i);
This gives error, but:
printf("%d",i+++i);
gives the output 11. In this case, the compiler read it as:
printf("%d",i+ ++i);
Why is this not done in first expression? i.e :
printf("%d",i+++++i);
Because of operator precedence i++++++i is treated as (i++)++ + i). This gives a compiler error because (i++) is not an lvalue.
Modifying the same variable multiple times between two sequence points is an Undefined Behavior according to §6.5 of language specifications
Between the previous and next sequence point an object shall have its stored value
modified at most once by the evaluation of an expression. Furthermore, the prior value
shall be read only to determine the value to be stored.(71)
71) This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;
i+++++i is parsed as i ++ ++ + i. It contains an invalid subexpression i ++ ++. Speaking formally, this expression contains a constraint violation, which is why it does not compile.
Meanwhile i+++i is parsed as i ++ + i (not as i + ++ i as you incorrectly believe). It does not contain any constraint violations. It produces undefined behavior, but is otherwise well-formed.
Also, it is rather naive to believe that printf("%d",i+++i) will print 11. The behavior of i+++i is undefined, meaning that there's no point in trying to predict the output.
In printf("%d",i+++++i);, the source text i+++++i is first processed according to this rule from C 2011 (N1570) 6.4 4:
If the input stream has been parsed into preprocessing tokens up to a given character, the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token…
This causes the lexical analysis to proceed in this way:
i can be a token, but i+ cannot, so i is the next token. This leaves +++++i.
+ and ++ can each be a token, but +++ cannot. Since ++ is the longest sequence that could be a token, it is the next token. This leaves +++i.
For the same reason, ++ is the next token. This leaves +i.
+ can be a token, but +i cannot, so + is the next token. This leaves i.
i can be a token, but i) cannot, so i is the next token.
Thus, the expression is i ++ ++ + i.
Then the grammar rules structure this expression as ((i ++) ++) + i.
When i++ is evaluated, the result is just a value, not an lvalue. Since ++ cannot be applied to a value that is not an lvalue, (i ++) ++ is not allowed.
After the compiler recognizes that the expression is semantically incorrect, it cannot go back and change the lexical analysis. Th C standard specifies that the rules must be followed as described above.
In i+++i, the code violates a separate rule. This is parsed as (i ++) + i. This expression both modifies i (in i ++) and separately accesses it (in the i of + i). This violates C 2011 (1570) 6.5 2:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
This rule uses some technical terms: In i ++, the effect of changing i is a side effect of ++. (The main effect is to produce the value of i.) The use of i in + i is a value computation of the scalar object i. And these two things are unsequenced, because the C standard does not specify whether producing the value of i for + i comes before or after changing i in i ++.

Why doesn't a+++++b work?

int main ()
{
int a = 5,b = 2;
printf("%d",a+++++b);
return 0;
}
This code gives the following error:
error: lvalue required as increment operand
But if I put spaces throughout a++ + and ++b, then it works fine.
int main ()
{
int a = 5,b = 2;
printf("%d",a++ + ++b);
return 0;
}
What does the error mean in the first example?
Compilers are written in stages. The first stage is called the lexer and turns characters into a symbolic structure. So "++" becomes something like an enum SYMBOL_PLUSPLUS. Later, the parser stage turns this into an abstract syntax tree, but it can't change the symbols. You can affect the lexer by inserting spaces (which end symbols unless they are in quotes).
Normal lexers are greedy (with some exceptions), so your code is being interpreted as
a++ ++ +b
The input to the parser is a stream of symbols, so your code would be something like:
[ SYMBOL_NAME(name = "a"),
SYMBOL_PLUS_PLUS,
SYMBOL_PLUS_PLUS,
SYMBOL_PLUS,
SYMBOL_NAME(name = "b")
]
Which the parser thinks is syntactically incorrect. (EDIT based on comments: Semantically incorrect because you cannot apply ++ to an r-value, which a++ results in)
a+++b
is
a++ +b
Which is ok. So are your other examples.
printf("%d",a+++++b); is interpreted as (a++)++ + b according to the Maximal Munch Rule!.
++ (postfix) doesn't evaluate to an lvalue but it requires its operand to be an lvalue.
!
6.4/4 says
the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token"
The lexer uses what's generally called a "maximum munch" algorithm to create tokens. That means as it's reading characters in, it keeps reading characters until it encounters something that can't be part of the same token as what it already has (e.g., if it's been reading digits so what it has is a number, if it encounters an A, it knows that can't be part of the number. so it stops and leaves the A in the input buffer to use as the beginning of the next token). It then returns that token to the parser.
In this case, that means +++++ gets lexed as a ++ ++ + b. Since the first post-increment yields an rvalue, the second can't be applied to it, and the compiler gives an error.
Just FWIW, in C++ you can overload operator++ to yield an lvalue, which allows this to work. For example:
struct bad_code {
bad_code &operator++(int) {
return *this;
}
int operator+(bad_code const &other) {
return 1;
}
};
int main() {
bad_code a, b;
int c = a+++++b;
return 0;
}
The compiles and runs (though it does nothing) with the C++ compilers I have handy (VC++, g++, Comeau).
This exact example is covered in the draft C99 standard(same details in C11) section 6.4 Lexical elements paragraph 4 which in says:
If the input stream has been parsed into preprocessing tokens up to a
given character, the next preprocessing token is the longest sequence
of characters that could constitute a preprocessing token. [...]
which is also known as the maximal munch rule which is used in in lexical analysis to avoid ambiguities and works by taking as many elements as it can to form a valid token.
the paragraph also has two examples the second one is an exact match for you question and is as follows:
EXAMPLE 2 The program fragment x+++++y is parsed as x ++ ++ + y, which
violates a constraint on increment operators, even though the parse x
++ + ++ y might yield a correct expression.
which tells us that:
a+++++b
will be parsed as:
a ++ ++ + b
which violates the constraints on post increment since the result of the first post increment is an rvalue and post increment requires an lvalue. This is covered in section 6.5.2.4 Postfix increment and decrement operators which says (emphasis mine):
The operand of the postfix increment or decrement operator shall have
qualified or unqualified real or pointer type and shall be a
modifiable lvalue.
and
The result of the postfix ++ operator is the value of the operand.
The book C++ Gotchas also covers this case in Gotcha #17 Maximal Munch Problems it is the same problem in C++ as well and it also gives some examples. It explains that when dealing with the following set of characters:
->*
the lexical analyzer can do one of three things:
Treat it as three tokens: -, > and *
Treat it as two tokens: -> and *
Treat it as one token: ->*
The maximal munch rule allows it to avoid these ambiguities. The author points out that it (In the C++ context):
solves many more problems than it causes, but in two common
situations, it’s an annoyance.
The first example would be templates whose template arguments are also templates (which was solved in C++11), for example:
list<vector<string>> lovos; // error!
^^
Which interprets the closing angle brackets as the shift operator, and so a space is required to disambiguate:
list< vector<string> > lovos;
^
The second case involves default arguments for pointers, for example:
void process( const char *= 0 ); // error!
^^
would be interpreted as *= assignment operator, the solution in this case is to name the parameters in the declaration.
Your compiler desperately tries to parse a+++++b, and interprets it as (a++)++ +b. Now, the result of the post-increment (a++) is not an lvalue, i.e. it can't be post-incremented again.
Please don't ever write such code in production quality programs. Think about the poor fellow coming after you who needs to interpret your code.
(a++)++ +b
a++ returns the previous value, a rvalue. You can't increment this.
Because it causes undefined behaviour.
Which one is it?
c = (a++)++ + b
c = (a) + ++(++b)
c = (a++) + (++b)
Yeah, neither you nor the compiler know it.
EDIT:
The real reason is the one as said by the others:
It gets interpreted as (a++)++ + b.
but post increment requires a lvalue (which is a variable with a name) but (a++) returns a rvalue which cannot be incremented thus leading to the error message you get.
Thx to the others to pointing this out.
I think the compiler sees it as
c = ((a++)++)+b
++ has to have as an operand a value that can be modified. a is a value that can be modified. a++ however is an 'rvalue', it cannot be modified.
By the way the error I see on GCC C is the same, but differently-worded: lvalue required as increment operand.
Follow this precesion order
1.++ (pre increment)
2.+ -(addition or subtraction)
3."x"+ "y"add both the sequence
int a = 5,b = 2;
printf("%d",a++ + ++b); //a is 5 since it is post increment b is 3 pre increment
return 0; //it is 5+3=8

Resources