Why is -(int) int being any int value ,an r-value? - c

#include<stdio.h>
int main()
{
int i = 10;
printf("%d", ++(-i));
return 0;
}
This is obviously an Compilation Error as post(pre)increment/decrement take l-values. So in this case -i is r-value BUT how and why?

The preincrement operator ++ (and other similar operators) requires an lvalue, which is an expression that not only has a type/value but also refers to an object. Roughly speaking, lvalues are things you could put on the left hand side of the = operator (but there are some exceptions) or put after the & (address-of) operator (but there are some exceptions here too).
The term rvalue is slang (not defined by the language standard) for expressions which are not lvalues. In the case of -i, i is an object, but there is no object -i; -i is just the resulting value from negating the value of i. Assigning something to -i is not possible because there is no object/storage it refers to.

The unary - operator produces a r-value. ++ cannot operate on r-value. Very right.
Now, to answer the "why", let me quote C11, chapter §6.5.3.3
The result of the unary - operator is the negative of its (promoted) operand.
The "result" here, is a computed value, it is not held by any variable. In other words, as mentioned in the comments, -i does not produce any object, so it is not an lvalue, it is considered as r-value, or non-lvalue.

Related

Why ++variable isn't treated as lvalue in C?

Consider the following C code:
#include <stdio.h>
int main(void) {
int a = 0;
printf("%d\n", ++a += 1);
}
++ has precedence over += so it should be evaluated first. So we have a on the left and 1 on the right. Now based on my understanding ++a should result in a (only changes its value) which is lvalue so why this statement gives the following error:
lvalue required as left operand of assignment
The prefix increment operator ++ results in the incremented value of its operand, however it is not an lvalue. Section 6.5.3.1p2 of the C standard: describes the semantics as follows:
The value of the operand of the prefix ++ operator is incremented.
The result is the new value of the operand after incrementation. The
expression ++E is equivalent to (E+=1). See the discussions of
additive operators and compound assignment for information on
constraints, types, side effects, and conversions and the effects of
operations on pointers.
Then section 6.5.16.2p3 regarding compound assignment operators states:
A compound assignment of the form E1 op = E2 is equivalent to the
simple assignment expression E1 = E1 op (E2), except that the lvalue
E1 is evaluated only once, and with respect to an
indeterminately-sequenced function call, the operation of a compound
assignment is a single evaluation.
And 6.5.16p3 regarding the assignment operator further states:
An assignment operator stores a value in the object designated by the
left operand. An assignment expression has the value of the left
operand after the assignment, but is not an lvalue.
So it is explicitly not allowed. Even if it was, an expression such as ++a += 1 would cause a to be modified more than once without an intervening sequence point which would trigger undefined behavior.
This is one of those place where C and C++ differ. C++ does in fact allow the result of the = operator, and by extension compound assingment and prefix ++/--, to be an lvalue.

How is the increment operator evaluated in C programs?

I have two expressions:
int a=5;
int c=++a;// c=6, a=6
int b=a++;// b=6, a=7
In the second instruction, the increment is evaluated first and in the third instruction, the increment is evaluated after the assignment.
I know that the increment operator has a higher priority. Can anyone explain to me why it's evaluated after assignment in the third expression?
The result is not related to the order of operations but to the definition of prefix ++ and postfix ++.
The expression ++a evaluates to the incremented value of a. In contrast, the expression a++ evaluates to the current value of a, and a is incremented as a side effect.
Section 6.5.2.4p2 of the C standard says the following about postfix ++:
The result of the postfix ++ operator is the value of the
operand. As a side effect, the value of the operand object is
incremented (that is, the value 1 of the appropriate type is added to
it).
And section 6.5.3.1p2 says the following about prefix ++:
The value of the operand of the prefix ++ operator is incremented. The
result is the new value of the operand after incrementation. The
expression ++E is equivalent to (E+=1)
++a and a++ are simply different operators, despite the same symbol ++. One is prefix-increment, one is postfix-increment. This has nothing to do with priority compared to assignment. (just like a - b and -a are different operators despite the same symbol -.)
EDIT: It was pointed out that this is about C and not C++... oops. So, the following explanation may be confusing if you only know C; all you need to know is that int& is a reference to an int, so it's like having a pointer but without the need to dereference it, so modifying a inside of these functions actually modifies the variable you passed into the functions.
You could imagine them like functions:
int prefixIncrement(int& a) {
return ++a;
}
...is the same as:
int prefixIncrement(int& a) {
a += 1;
return a;
}
And:
int postfixIncrement(int& a) {
return a++;
}
...is the same as:
int postfixIncrement(int& a) {
int old = a;
a += 1;
return old;
}
For nitpickers: Yes, actually we'd need move semantics on the return value for postfixIncrement.

"The only operator that gives back a value is the de-referencing operator"

So I am a beginner to C.
I was going through text about l-value and r-value when I came across this in one of my study materials:
"We talk about l-value and r-value with respect to assignment operator =.
The only operator which gives a value back is the dereferencing
operator."
This confuses me because don't the increment/decrement operators also give a value? Then how is dereferencing the only operator that gives a value back?
I think this is a typo and is supposed to say
The only operator which gives an l-value back is the dereferencing operator.
It isn't strictly true. For example, the [], . and -> operators also give back lvalues (the standard spells it without a hyphen) so that you can write
a[5] = 17;
s.x = 42;
p->y = 17;
I disagree with this author.
All operator-expressions, whether, unary, binary or ternary, evaluate into a value.
Even restricting ourselves to unary operators, all ten of these would seem to "give a value back" (eg. The expression evaluates to a value):
& - AddressOf: returns the memory address of a variable
* - Dereference: returns the value stored at a memory address
! - Logical Not
~ - Binary Not
++x - Prefix increment
x++ - Postfix increment
--x - Prefix decrement
x-- - Postfix decrement
sizeof(x) - The Size operator (not a run-time operation, however)
(type)(x) - The Cast Operator converts a value of one type into another type.
If the sentence was meant to be: "The only operator which gives a l-value back is the dereferencing operator.", then it makes more sense, but is still imperfect and imprecise:
Examples:
y = x; // Simple Assignment
*y = x; // Assignment with dereference operator
y[5] = x; // Wait? Is this another operator forming an L-Value?
y.f = x; // Another one?
y->f = x; // The author was clearly wrong.

(p++)->x Why are the parentheses unnecessary? (K&R)

From page 123 of The C Programming Language by K&R:
(p++)->x increments p after accessing x. (This last set of parentheses is unnecessary. Why?)
Why is it unnecessary considering that -> binds stronger than ++?
EDIT: Contrast the given expression with ++p->x, the latter is evaluated as ++(p->x) which would increment x, not p. So in this case parentheses are necessary and we must write (++p)->x if we want to increment p.
The only other possible interpretation is:
p++(->x)
and that doesn't mean anything. It's not even valid. The only possible way to interpret this in a valid way is (p++)->x.
Exactly because -> binds stronger than ++. (it doesn't, thanks #KerrekSB.)
increments p after accessing x.
So first you access x of p, then you increment p. That perfectly matches the order of evaluation of the -> and the + operators.
Edit: aww, these edit's...
So what happens when you write ++p->x is that it could be interpreted either as ++(p->x) or as (++p)->x (which one is actually chosen is just a matter of language design, K&R thought it would be a good idea to make it evaluate as in the first case). The thing is that this ambiguity doesn't exist in the case of p++->x, since it can only be interpreted as (p++)->x. The other alternatives, p(++->x), p(++->)x and p++(->x) are really just syntactically malformed "expressions".
The maximal munch strategy says that p++->x is divided into the following preprocessing tokens:
p then ++ then -> then x
In p++->x expression there are two operators, the postfix ++ operator and the postifx -> operator. Both operators being postfix operators, they have the same precedence and there is no ambiguity in parsing the expression. p++->x is equivalent to (p++)->x.
For ++p->x expression, the situation is different.
In ++p->x, the ++ is not a postfix operator, it is the ++ unary operator. C gives postfix operators higher precedence over all unary operators and this is why ++p->x is actually equivalent to ++(p->x).
EDIT: I changed the first part of the answer as a result of Steve's comment.
Both post-increment and member access operator are postfix expressions and bind the same. Considering that they apply to the primary or postfix expression to the left, there can't be ambiguity.
In
p++->x
The postfix-++ operator can apply only to the expression to the left of it (i.e. to p).
Similarly ->x can only be an access to the expression to its left, which is p++. Writing that expression as (p++) is not needed, but also does no harm.
The "after" in your description of the effects, does not express temporal order of increment and member access. It only expresses that the result of p++ is the value p had before the increment and that that value is the value used for the member access.
The expresion p++ results in a pointer with the value of p. Later on, the ++ part is performed, but for the purposes of interpreting the expression, it may just as well not be there. ->x makes the compiler add the offset for the member x to the original address in p and access that value.
If you change the statement to :
p->x; p++;
it would do exactly the same thing.
The order of precedence is actually exactly the same, as can be seen here - but it doesn't really matter.

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