This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 9 years ago.
hello I am learning basics of C programming language, recently i have studied about post and pre increment/decrement operators and also about lvalue and rvalue, the following program shows an error, lvalue required, according to me it should give a value of 6, Can anyone please explain why?
int main(){
int x = 8, y;
y = --x--;
printf("y=%d",y);
return 0;
}
Please explain, why is it so?
Well, let's see what is happening in --x--.
At first, post-decrement executes: --(x--).
(x--) = 7.
After that result of this operation is placed to the original structure:
--7 - doesn't make sense - thus you get lvalue required error
The statement y = --x--; will give you the following error on compilation in C. lvalue required. This is because the post decrement operator -- will return an rvalue after operating on the variable x. So there are no lvalue to perform the pre decrement operator -- afterwards.
But this is one point where C and C++ differs. In C the following statement will also give you the same error lvalue required.
y = (--x)--;
But in C++ the statement y = (--x)--; will compile fine and the value of y is 7. Because unlike C, C++ returns an lvalue after performing the pre decrement operator on variable x.
L Value is left operand of assignment operator which should refer to memory location.As explained by #Pavel your Lvalue is becoming a value not object so you are getting error.
--x means x = x-1 but in your case it is becoming --7 which will be equivalent to 7 =7-1 which is definitely not valid expression.
Other than this more than one operation on same variable without any sequence point in between, results undefined behaviour.
C order of operations specifies that postfix operators have precedence over the prefix operators. The -- postfix operator returns the current value (an rvalue) of the operand and then decrements the operand. Then the prefix decrement operator would be applied...but the decrement/increment operators need lvalue operands since they by definition modify their operands. So, as the compiler says, an lvalue is required.
You should not use it at a time because you will not understand the behavior of compiler. So, you need to guide your code so that they will forced to do what you like.
Now come to your point. If you want to decrease the value by one you can use a-- or --a. They will do the same. If a = 5 and you use b=a-- you will get b = 5 and a = 4 where if you use b=--a you will get b = 4 and a = 4 in --a the value is assigned immediately and in a-- value will be assigned after statement is complete. Hope you are clear.
L value required error shown when it doesn't find any suitable variable where it can be assigned.
Related
This question already has answers here:
Post-increment on a dereferenced pointer?
(13 answers)
Closed 3 years ago.
Shouldn't ptrj value be 4 after the execution of *ptrj++?
int j=3,*ptrj = NULL;
ptrj = &j;
*ptrj++;
printf("%i",*ptrj);
*ptrj++ is the same as *(ptrj++). What you expect is instead (*ptrj)++. You should look up operator precedence to learn more about which operators that acts before others. To understand what ptrj++ does, you should read about pointer arithmetic. But here is a quick explanation:
*(ptrj++) returns the value that ptrj points to (3), and THEN increments ptrj to point to the next value.
(*ptrj)++ returns the value that ptrj points to (3), and THEN increments the value that ptrj points at from 3 to 4.
This means that what you're printing is the value at address &j + 1, which is the value that lies right after the variable j in memory. and this is undefined behavior. As Sourav pointed out, you would get a warning that points you to this if you enable compiler warnings.
The only difference between *ptrj++ and ptrj++ is what it is returning. And since you don't use the return value, your code is equivalent to:
int j=3,*ptrj = NULL;
ptrj = &j;
ptrj++;
printf("%i",*ptrj);
If you compile the program with warnings enabled, you'll see
source_file.c:9:5: warning: value computed is not used [-Wunused-value]
*ptrj++;
^
That means, the value computation is useless.
In other words, according to the operator precedence *ptrj++; is same as *(ptrj++);, and as per the post-increment operator property, the value of the operation is the value of the operand, and the value is increased as the side-effect.
Quoting C11, chapter
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). [....]
So, this is same as
*ptr;
ptr++;
If you want to increment that value at the address, you need to enforce the operator precedence by using explicit parenthesis, like
(*ptrj)++; // first get the value, then update the value.
*ptrj++ is equivalent to *(ptrj++).
desired output can be achieved using (*ptrj)++.
Please refer https://www.geeksforgeeks.org/c-operator-precedence-associativity/ to get how operator works.
Precedence of postfix ++ is higher than *. The expression *ptrj++ is treated as *(ptrj++) as the precedence of postfix ++ is higher than *.If you want to print 4 ( ie ptrj+1 ),You should use the following code:-
int j=3,*ptrj = NULL;
ptrj = &j;
(*ptrj)++;
printf("%i",*ptrj);
return 0;
To know more about operator precedence, refer follow link:
https://en.cppreference.com/w/c/language/operator_precedence
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 4 years ago.
Consider the following line of code.
int i = 2;
i = i++
The second line of code has been identified as undefined. I know this question has been asked before several times and example being this.
But nowhere could I see the issue of operator precedence being addressed in this issue. It has been clearly mentioned that postfix operator precedes assignment operator.
i = (i++)
So clearly i++ will be evaluated first and this value of i is the assigned to i again.
This looks like this particular undefined behavior is contradicting the precedence rule.
Similar to this is the code:
int i = 2;
i++ * i++;
Here according to operator precedence the code can be written as
int i =2;
(i++) * (i++)
Now we do not know whether the (i++) in LHS or RHS of '*' operator is going to be evaluated first. But either way it is going produce the same result. So how is it undefined?
If we write say:
int p;
p = f1() + f2()
where f1() and f2() are defined functions then obviously it's clear we can't decide whether f1() or f2() is going to be evaluated first as precedence rules does not specify this. But a confusion like this does not seem to arise in the current problem.
Please explain.
I do not understand why this question got a negative vote. I needed a clarity between operator precedence and UB and I have seen no other question addressing it.
What you're looking for is in section 6.5 on Expressions, paragraph 3 of the C standard:
The grouping of operators and operands is indicated by the syntax.
Except as specified later, side effects and value computations of
subexpressions are unsequenced.
This means that the side effect of incrementing (or decrementing) via the ++ or -- operators doesn't necessarily happen immediately when the operator is encountered. The only guarantee is that it happens before the next sequence point.
In the case of i = i++;, there is no sequence point in the evaluation of the operands of = nor in the evaluation of postfix ++. So an implementation is free to perform assigning the current value of i to itself and the side effect of incrementing of i in any order. So i could potentially be either 2 or 3 in your example.
This goes back to paragraph 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.
Since i = i++ attempts to update i more than once without a sequence point, it invokes undefined behavior. The result could be 2 or 3, or something else might happen as a result of optimizations for example.
The reason that this is not undefined:
int p;
p = f1() + f2()
Is because a variable is not being updated more than once in a sequence point. It could however be unspecified behavior if both f1 and f2 update the same global variables, since the evaluation order is unspecified.
The problem with using
i = i++
is that the order in which the address of i is accessed to read and write is not specified. As a consequence, at the end of that line, the value of i could be 3 or 2.
When will it be 3?
Evaluate the RHS - 2
Assign it to the LHS. i is now 2.
Increment i. i is now 3.
When will it be 2?
Evaluate the RHS - 2
Increment i. i is now 3.
Assign the result of evaluating the RHS to the LHS. i is now 2.
Of course, if there is a race condition, we don't know what's going to happen.
But nowhere could I see the issue of operator precedence being addressed in this issue.
Operator precedence only affects how expressions are parsed (which operands are grouped with which operators) - it has no effect on how expressions are evaluated. Operator precedence says that a * b + c should be parsed as (a * b) + c, but it doesn't say that either a or b must be evaluated before c.
Now we do not know whether the (i++) in LHS or RHS of '*' operator is going to be evaluated first. But either way it is going produce the same result. So how is it undefined?
Because the side effect of the ++ operator does not have to be applied immediately after evaluation. Side effects may be deferred until the next sequence point, or they may applied before other operations, or sprinkled throughout. So if i is 2, then i++ * i++ may be evaluated as 2 * 2, or 2 * 3, or 3 * 2, or 2 * 4, or 4 * 4, or something else entirely.
OPERATOR PRECEDENCE DOES NOT RESOLVE UNDEFINED EXPRESSION ISSUES.
Sorry for shouting, but people ask about this all the time. I'm afraid I have to say your research on this question must not have been very thorough, if you didn't see this aspect being discussed.
See for example this essay.
The expression i = i++ tries to assign to object i twice. It's therefore undefined. Period. Precedence doesn't save you.
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 7 years ago.
some body please tell me what will be the value of x after(in c language)
x=1;
x=x--&&++x;
I think it should be 0 because x&&++x will give 1 and post decrement will make it 0.
But when I entered this on computer result was 1.
Why post decrement is not working here.
I am thinking like this:
precedence of pre increment is above && so both x should be treated as 2 (Boolean value true ) so x&&++x will give 1 and the post-decrement should decrement it to 0.
This is not a duplicate question as this is not the case of undefined behavior its about how post-decrement works.
x=x--&&++x;
This causes undefined behaviour as value of x is changed more than once between two sequence points.
Expression x-- && ++x is well defined as it has internal sequence point due to && , but when you assign it to x , it causes undefined behaviour.
Therefore ,expression exhibits undefined behaviour.
C99 §6.5: “2. 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.”
While the result of (x--)&&(++x); is well defined, due to short circuit evaluation.
the result of your assignment
x = (x--)&&(++x); is not.
A simpler example would be:
x = x--;
which, as Paul and Art note in the comments:
modifies the value of x twice within the same expression without a
sequence point between the modifications.
EDIT: fixed my initial errornous answer, which stated that the result of the assignment is defined.
Inspite of the fact that there are exams in my university I wasn't able to stop thinking about this question and I think I have finally found the solution.
Firstly, post decrement operator will be executed as it is in the left of &&, it will decrement the value of x to 0 but x-- will be 1(previous value of x ) as left side is 1 right side will be executed here ++x will assign value 1 to x and value of ++x will also be 1 so && operator will return value 1.Now, although there is no sequence point between pre-increment operator and assignment operator both are assigning value 1 to x so this is totally defined that value of x will be 1 after the whole code is executed.
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 8 years ago.
I have another C pointers question.
Consider executing the following program:
int x[5] = {0,3,5,7,9};
int* y = &x[2];
*(y+2) = *(y--);
What values does the array x hold afterwards?
What the hell is going on with y--? I know how *(y+2) works, and understand the rest, but not how y-- ties in with the rest.
Also, the answer given is {0, 3, 5, 5, 9}.
There's no sequence point between y-- and y + 2 in *(y+2) = *(y--);, so whether y + 2 refers to &x[4] or &x[3] is unspecified. Depending on how your compiler does things, you can either get 0 3 5 5 9 or 0 3 5 7 5.
What it means that there is no sequence point between the two expressions is, in a nutshell, that it is not specified whether the side effects of one operation (--y in this case) have been applied by the time the other (y - 2) is evaluated. You can read more about sequence points here.
ISO/IEC 9899:201x
6.5 Expressions
p2: 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. If there are multiple allowable orderings of the
subexpressions of an expression, the behavior is undefined if such an unsequenced side
effect occurs in any of the orderings.
You should not trust the answers given by your professor in this case.
Expanding on Wintermute's answer a bit...
The problem is with the statement
*(y+2) = *(y--);
The expression y-- evaluates to the current value of y, and as a side effect decrements the variable. For example:
int a = 10;
int b;
b = a--;
After the above expression has been evaluated, b will have the value 10 and a will have the value 9.
However, the C language does not require that the side effect be applied immediately after the expression has been evaluated, only that it be applied before the next sequence point (which in this case is at the end of the statement). Neither does it require that expressions be evaluated from left to right (with a few exceptions). Thus, it's not guaranteed that the value of y in y+2 represents the value of y before or after the decrement operation.
The C language standard explicitly calls operations like this out as undefined behavior, meaning that the compiler is free to handle the situation in any way it wants to. The result will vary based on the compiler, compiler settings, and even the surrounding code, and any answer will be equally correct as far as the language definition is concerned.
In order to make this well-defined and give the same result, you would need to decrement y before the assignment statement:
y--;
*(y+2) = *y;
This is consistently one of the most misunderstood and mis-taught aspects of the C language. If your professor is expecting this particular result to be well-defined, then he doesn't know the language as well as he thinks he does. Then again, he's not unique in that respect.
Repeating and expanding on the snippet from the C 2011 draft standard that Wintermute posted:
6.5 Expressions
...
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. If there are multiple allowable orderings of the
subexpressions of an expression, the behavior is undefined if such an unsequenced side
effect occurs in any of the orderings.84)
3 The grouping of operators and operands is indicated by the syntax.85) Except as specified
later, side effects and value computations of subexpressions are unsequenced.86)
84) This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;
85) The syntax specifies the precedence of operators in the evaluation of an expression, which is the same
as the order of the major subclauses of this subclause, highest precedence first. Thus, for example, the
expressions allowed as the operands of the binary + operator (6.5.6) are those expressions defined in
6.5.1 through 6.5.6. The exceptions are cast expressions (6.5.4) as operands of unary operators
(6.5.3), and an operand contained between any of the following pairs of operators: grouping
parentheses () (6.5.1), subscripting brackets [] (6.5.2.1), function-call parentheses () (6.5.2.2), and
the conditional operator ? : (6.5.15).
Within each major subclause, the operators have the same precedence. Left- or right-associativity is
indicated in each subclause by the syntax for the expressions discussed therein.
86) In an expression that is evaluated more than once during the execution of a program, unsequenced and
indeterminately sequenced evaluations of its subexpressions need not be performed consistently in
different evaluations.
Emphasis added. Note that this has been true since the C89 standard, although the wording has changed a bit since then.
"Unsequenced" simply means it's not guaranteed that one operation is completed before the other. The assignment operator does not introduce a sequence point, so it's not guaranteed that the LHS of the expression is evaluated before the RHS.
Now for the hard bit - your professor obviously expects a specific behavior for these kinds of expressions. If he gives a test or a quiz that asks what the result of something like a[i] = i--; will be, he's probably not going to accept an answer of "the behavior is undefined", at least not on its own. You might want to discuss the answers Wintermute and I have given with him, along with the sections of the standard quoted above.
The problem is in this statement.
*(y+2) = *(y--);
Because in C, reading a variable twice in an expression (in which it's modified) has undefined behavior.
Another example is:
i = 5;
v[i] = i++;
In this case the most likely to happen (AFAIK) is that the compiler first evalue RHS or LHS, if LHS is first evaluated, then we will have v[5] = 5; and after the assignment i will be equal to 6, if instead of that RHS is evaluated in the first place, then we will have that the evaluation of the right side will be equal to 5, but when we start evaluating the left side i will be equal to 6, so we will end up with v[6] = 5;, however, given the quote "undefined behavior allow the compiler to do anything it chooses, even to make demons fly out of your nose" you should not expect one of those options, instead of that you should expect anything, because it depends on the compiler what happens.
First of all int x[5] = {0, 3, 5, 7, 9} means
x[0] = 0, x[1] = 3, x[2] = 5, x[3] = 7, x[4] = 9
Next int *y = &x[2] Here you are trying to use pointer y to point the address of x[2]
Now here comes to your confusion *(y + 2) means you are pointing address of x[4]
and *(y--), here y-- is a post decrement operator, hence first of all the the value at *y must be used which is x[2] = 5 so now the value assigned is x[4] = 5.
The final output would be 0 3 5 7 5
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 9 years ago.
int a[]={10,20,30,40};
int x=0;
int v=a[++x]+ ++x + a[--x];
printf("%d",v);
What will be the output of this program??
Completely confused with the output. No way it is going to be done according to my operator precedence knowledge.
According to me, in this expression Array subscripting [] has highest precendence and should be executed first. so both [] should be executed first from left to right. In this case value of x will increment first, then decrement and finally come back to 0. so expression will become int v=a[0] + ++x + a[0]. Then the pre increment is having highest precedence and it will be incremented to 1. so our expression will become int v=a[0]+1+a[0]. so final output will be 21.
But this is not the case. I have checked on different compiler implementations and no one prints 21.
I am much surprised because the value printed is 43, which is no where understandable to me. That's why I want someone to help me understand and come to the result 43.
The link which others have suggested is using only increment and same rvalue and lvalue cases. But this is somewhat different and not clear. I tried to contruct expression tree for this and solve but 43 is no where in scope.
Output of this code:
int v=a[++x]+ ++x + a[--x];
is undefined and it depends on the compiler implementation.