Strange behavior from a simple C program - c

If I run the following code, graph[0][0] gets 1 while graph[0][1] gets 4.
In other words, the line graph[0][++graph[0][0]] = 4; puts 1 into graph[0][0] and 4 into graph[0][1].
I would really appreciate if anyone can offer reasonable explanation.
I observed this from Visual C++ 2015 as well as an Android C compiler (CppDriod).
static int graph[10][10];
void main(void)
{
graph[0][++graph[0][0]] = 4;
}

Let's break it down:
++graph[0][0]
This pre-increments the value at graph[0][0], which means that now graph[0][0] = 1, and then the value of the expression is 1 (because that is the final value of graph[0][0]).
Then,
graph[0][/*previous expression = 1*/] = 4;
So basically, graph[0][1] = 4;
That's it! Now graph[0][0] = 1 and graph[0][1] = 4.

First let's see what is the unary (prefix) increment operator does.
The value of the operand of the prefix ++ operator is incremented. The result is the new value of the operand after incrementation.
So, in case of
graph[0][++graph[0][0]] = 4;
first, the value of graph[0][0] is incremented by 1, and then the value is used in indexing.
Now, graph being a static global variable, due to implicit initialization, all the members in the array are initialized to 0 by default. So, ++graph[0][0] increments the value of graph[0][0] to 1 and returns the value of 1.
Then, the simpllified version of the instrucion looks like
graph[0][1] = 4;
Thus, you get
graph[0][0] as 1
graph[0][1] as 4.
Also, FWIW, the recommended signature of main() is int main(void).

You are adding one to graph[0][0], by doing ++graph[0][0]. And then setting graph[0][1] to 4. Maybe you want to do graph[0][graph[0][0]+1] = 4

At first your variable graph[10][10] is static so it will be initialized with value 0.
Then line graph[0][++graph[0][0]] = 4 ; here graph[0][0] = 0 in expression you just incrementing the value of graph[0][0] so basically you assigning graph[0][1] = 4; yourself
Note that you have used pre-increment operator (++x) so it first get incremented and value is changed but if you would have use post-increment operator(x++) then graph[0][0] = 4; itself

Let's line up the facts about this expression
graph[0][++graph[0][0]] = 4;
Per 6.5.1, the computation of the array index ++graph[0][0] is sequenced before the computation of array element graph[0][++graph[0][0]], which in turn is sequenced before the computation of the entire assignment operator.
The value of ++graph[0][0] is required to be 1. Note that this does not mean that the whole pre-increment together with its side-effects has to "happen first". It simply means that the result of that pre-increment (which is 1) has to be computed first. The actual modification of graph[0][0] (i.e. changing of graph[0][0] from 0 to 1) might happen much much later. Nobody knows when it will happen exactly (sometime before the end of the statement).
This means that the element being modified by the assignment operator is graph[0][1]. This is where that 4 should go to. Assignment of 4 to graph[0][1] is also a side-effect of = operator, which will happen sometime before the end of the statement.
Note, that in this case we could conclusively establish that ++ modifies graph[0][0], while = modifies graph[0][1]. We have two unsequenced side-effects (which is dangerous), but they act on two different objects (which makes them safe). This is exactly what saves us from undefined behavior in this case.
However, this is dependent on the initial value of graph array. If you try this
graph[0][0] = -1;
graph[0][++graph[0][0]] = 4;
the behavior will immediately become undefined, even though the expression itself looks the same. In this case the side-effect of ++ and the side-effect of = are applied to the same array element graph[0][0]. The side-effects are not sequenced with relation to each other, which means that the behavior is undefined.

Related

Multiple unsequenced modifications to 'a',a = a++ [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 1 year ago.
Why i can't do the following in Objective-C?
a = (a < 10) ? (a++) : a;
or
a = (a++)
The ++ in a++ is a post-increment. In short, a = a++ does the following:
int tmp = a; // get the value of a
a = a + 1 //post-increment a
a = tmp // do the assignment
As noted by others, in C this is actually undefined behavior and different compilers can order the operations differently.
Try to avoid using ++ and -- operators when you can. The operators introduce side effects which are hard to read. Why not simply write:
if (a < 10) {
a += 1;
}
To extend Sulthan's answer, there are several problem with your expressions, at least the simple assignment (case 2).
A. There is no sense in doing so. Even a++ has a value (is a non-void expression) that can be assigned, it automatically assigns the result to a itself. So the best you can expect is equivalent to
a++;
The assignment cannot improve the assignment at all. But this is not the error message.
B. Sulthans replacement of the statement is a better case. It is even worse: The ++ operator has the value of a (at the beginning of the expression) and the effect to increment a at some point in future: The increment can be delayed up to the next sequence point.
The side effect of updating the stored value of the operand shall occur between the previous and the next sequence point.
(ISO/IEC 9899:TC3, 6.5.2.4, 2)
But the assignment operator = is not a sequence point (Annex C).
The following are the sequence points described in 5.1.2.3:
[Neither assignment operator nor ) is included in the list]
Therefore the expression can be replaced with what Sulthan said:
int tmp = a; // get the value of a
a = a + 1 //post-increment a
a = tmp // do the assignment
with the result, that a still contains the old value.
Or the expression can be replaced with this code …:
int tmp = a; // get the value of a
a = tmp // assignemnt
a = a + 1 // increment
… with a different result (a is incremented). This is what the error message says: There is no defined sequence (order the operations has to be applied.)
You can insert a sequence point using the comma operator , (what is the primary use of it), …
a++, a=a; // first increment, then assign
… but this shows the whole leak of meaning of what you want to do.
It is the same with your first example. Though ? is a sequence point …:
The following are the sequence points described in 5.1.2.3:
… The end of the first operand of the following operators: […] conditional ? (6.5.15);[…].
… both the increment (a++) and the assignment (a=) are after the ? operator is evaluated and therefore unsequenced ("in random order") again.
To make the comment "Be careful" more concrete: Don't use an incremented object in an expression twice. (Unless there is a clear sequence point).
int a = 1;
… = a++ * a;
… evaluates to what? 2? 1? Undefined, because the increment can take place after reading a "the second time".
BTW: The Q is not related to Objective-C, but to pure C. There is no Objective-C influence to C in that point. I changed the tagging.

C language basics 1

What is the difference between a++ and a=a+1 in C if a is a variable.
Tell me the difference between the following assignments;
x=a+1;
x=a++;
I am not able to find a convincing explanation on Google.Please explain the difference clearly and step by step.
a = a+1; calculates the result of a+1 and assigns it to a.
a++; increments a by 1, but evaluates to the previous value of a.
++a; increments a by 1, and evaluates to the new value of a.
a += 1 is identical to ++a;.
So for example:
x = a++; → a will be incremented by 1, and the previous value of a will be assigned to x.
x = ++a; → a will be incremented by 1, and the new value of a will be assigned to x.
x=a+1 just sets the value of x.
x=a++ first sets x to the value of a, and then increments a. a++ is an operation in itself, and you could call it as a single statement to increment a, without assigning it to x whatsoever.
FYI, there is also ++a, which could be used like this:
x=++a. In this case, a is incremented first, and then the incremented value is assigned to x. In either case, the ++ operator modifies a, which is not the case for a+1.
From the C11 Standard (draft):
6.5.2.4 Postfix increment [...] operator[...]
[...]
2 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
int a = 0;
int x = a++;
results in a being 1 and x being 0.
x = a++ returns the value of a to the variable x first and later it is incremented.
x = a+1 Here a+1 is evaluated and the result is stored in x
3 differences
Return value and side effect
// a is incremented, but its former value is assigned to x
x=a++; //
// a is unchanged. The sum of `a+1`is assigned to x
x=a+1;
Operator precedence. post-fix ++ (aka Suffix increment) is higher precedence than simple addition.
++ only works with integer and non-void* pointer types. +1 works with all scalar type including double.
int a;
x=a++; // valid
x=a+1; // valid
double a;
x=a++; // invalid
x=a+1; // valid

What does " = " instead of " == " mean in c if statement?

#include <stdio.h>
int main(){
int b = 10,a;
if (a = 5){
printf("%d",b);
}
}
In the above program if statement always returns true even if i change the data type of the variable "a" from "int" to "char".
What does = mean in the if statement??
= is an assignment operator in C. According to C99 6.5.16:
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.
It means that expression a = 5 will return 5 and therefore instructions inside if block will be executed. In contrary, if you replaced it with a = 0 then 0 would be returned by assignment expression and instructions inside if would not be executed.
A single = means an assignment operator, that means you are changing the value of a and using this value in the if statement.
if(a = 5) {
// some code
}
is the same of:
a = 5;
if(a) {
// some code
}
The == means a operation of logical equivalence, witch will return 1 if the two values are the same or 0 if they aren't the same.
Assignment operator returns the assigned value back.
"if" statement decides to true if checked value is other than zero
So:
"if (a=0)" returns false
"if (a=x) where x!= 0" returns true
Thus you should use "==" operator in the if statement as other friends told.
The single = will assign the value 5 to a. Assignment will evaluate true if the assignment value evaluates true (i.e. not 0, null etc). If it evaluates true, the function will branch into the if statement block. And there's the side effect that a gets value 5.
Please note that in C it is allowed in a boolean expression to use the assignment operator. Because of that = as assignment must be a different symbol than = for comparisson.
Because in a language such as BASIC there can be no confusion of whether the programmer means assignment or comparisson, BASIC uses the same symbol for the two meanings:
C:
if ((a=5)==5) ... // a is set to 5 and then compared to 5
Basic:
a = 5 ' assignment
If (a = 5) Then ' comparison

Why does a=(b++) have the same behavior as a=b++?

I am writing a small test app in C with GCC 4.8.4 pre-installed on my Ubuntu 14.04. And I got confused for the fact that the expression a=(b++); behaves in the same way as a=b++; does. The following simple code is used:
#include <stdint.h>
#include <stdio.h>
int main(int argc, char* argv[]){
uint8_t a1, a2, b1=10, b2=10;
a1=(b1++);
a2=b2++;
printf("a1=%u, a2=%u, b1=%u, b2=%u.\n", a1, a2, b1, b2);
}
The result after gcc compilation is a1=a2=10, while b1=b2=11. However, I expected the parentheses to have b1 incremented before its value is assigned to a1.
Namely, a1 should be 11 while a2 equals 10.
Does anyone get an idea about this issue?
However, I expected the parentheses to have b1 incremented before its value is assigned to a1
You should not have expected that: placing parentheses around an increment expression does not alter the application of its side effects.
Side effects (in this case, it means writing 11 into b1) get applied some time after retrieving the current value of b1. This could happen before or after the full assignment expression is evaluated completely. That is why a post-increment will remain a post-increment, with or without parentheses around it. If you wanted a pre-increment, place ++ before the variable:
a1 = ++b1;
Quoting from the C99:6.5.2.4:
The result of the postfix ++ operator is the value of the operand.
After the result is obtained, the value of the operand is incremented.
(That is, the value 1 of the appropriate type is added to it.) See the
discussions of additive operators and compound assignment for
information on constraints, types, and conversions and the effects of
operations on pointers. The side effect of updating the stored value
of the operand shall occur between the previous and the next sequence
point.
You can look up the C99: annex C to understand what the valid sequence points are.
In your question, just adding a parentheses doesn't change the sequence points, only the ; character does that.
Or in other words, you can view it like there's a temporary copy of b and the side-effect is original b incremented. But, until a sequence point is reached, all evaluation is done on the temporary copy of b. The temporary copy of b is then discarded, the side effect i.e. increment operation is committed to the storage,when a sequence point is reached.
Parentheses can be tricky to think about. But they do not mean, "make sure that everything inside happens first".
Suppose we have
a = b + c * d;
The higher precedence of multiplication over addition tells us that the compiler will arrange to multiply c by d, and then add the result to b. If we want the other interpretation, we can use parentheses:
a = (b + c) * d;
But suppose that we have some function calls thrown into the mix. That is, suppose we write
a = x() + y() * z();
Now, while it's clear that the return value of y() will be multiplied by the return value of z(), can we say anything about the order that x(), y(), and z() will be called in? The answer is, no, we absolutely cannot! If you're at all unsure, I invite you to try it, using x, y, and z functions like this:
int x() { printf("this is x()\n"); return 2; }
int y() { printf("this is y()\n"); return 3; }
int z() { printf("this is z()\n"); return 4; }
The first time I tried this, using the compiler in front of me, I discovered that function x() was called first, even though its result is needed last. When I changed the calling code to
a = (x() + y()) * z();
the order of the calls to x, y, and z stayed exactly the same, the compiler just arranged to combine their results differently.
Finally, it's important to realize that expressions like i++ do two things: they take i's value and add 1 to it, and then they store the new value back into i. But the store back into i doesn't necessarily happen right away, it can happen later. And the question of "when exactly does the store back into i happen?" is sort of like the question of "when does function x get called?". You can't really tell, it's up to the compiler, it usually doesn't matter, it will differ from compiler to compiler, if you really care, you're going to have to do something else to force the order.
And in any case, remember that the definition of i++ is that it gives the old value of i out to the surrounding expression. That's a pretty absolute rule, and it can not be changed just by adding some parentheses! That's not what parentheses do.
Let's go back to the previous example involving functions x, y, and z. I noticed that function x was called first. Suppose I didn't want that, suppose I wanted functions y and z to be called first. Could I achieve that by writing
x = z() + ((y() * z())?
I could write that, but it doesn't change anything. Remember, the parentheses don't mean "do everything inside first". They do cause the multiplication to happen before the addition, but the compiler was already going to do it that way anyway, based on the higher precedence of multiplication over addition.
Up above I said, "if you really care, you're going to have to do something else to force the order". What you generally have to do is use some temporary variables and some extra statements. (The technical term is "insert some sequence points.") For example, to cause y and z to get called first, I could write
c = y();
d = z();
b = x();
a = b + c * d;
In your case, if you wanted to make sure that the new value of b got assigned to a, you could write
c = b++;
a = b;
But of course that's silly -- if all you want to do is increment b and have its new value assigned to a, that's what prefix ++ is for:
a = ++b;
Your expectations are completely unfounded.
Parentheses have no direct effect on the order of execution. They don't introduce sequence points into the expression and thus they don't force any side-effects to materialize earlier than they would've materialized without parentheses.
Moreover, by definition, post-increment expression b++ evaluates to the original value of b. This requirement will remain in place regardless of how many pair of parentheses you add around b++. Even if parentheses somehow "forced" an instant increment, the language would still require (((b++))) to evaluate to the old value of b, meaning that a would still be guaranteed to receive the non-incremented value of b.
Parentheses only affects the syntactic grouping between operators and their operands. For example, in your original expression a = b++ one might immediately ask whether the ++ apples to b alone or to the result of a = b. In your case, by adding the parentheses you simply explicitly forced the ++ operator to apply to (to group with) b operand. However, according to the language syntax (and the operator precedence and associativity derived from it), ++ already applies to b, i.e. unary ++ has higher precedence than binary =. Your parentheses did not change anything, it only reiterated the grouping that was already there implicitly. Hence no change in the behavior.
Parentheses are entirely syntactic. They just group expressions and they are useful if you want to override the precedence or associativity of operators. For example, if you use parentheses here:
a = 2*(b+1);
you mean that the result of b+1 should be doubled, whereas if you omit the parentheses:
a = 2*b+1;
you mean that just b should be doubled and then the result should be incremented. The two syntax trees for these assignments are:
= =
/ \ / \
a * a +
/ \ / \
2 + * 1
/ \ / \
b 1 2 b
a = 2*(b+1); a = 2*b+1;
By using parentheses, you can therefore change the syntax tree that corresponds to your program and (of course) different syntax may correspond to different semantics.
On the other hand, in your program:
a1 = (b1++);
a2 = b2++;
parentheses are redundant because the assignment operator has lower precedence than the postfix increment (++). The two assignments are equivalent; in both cases, the corresponding syntax tree is the following:
=
/ \
a ++ (postfix)
|
b
Now that we're done with the syntax, let's go to semantics. This statement means: evaluate b++ and assign the result to a. Evaluating b++ returns the current value of b (which is 10 in your program) and, as a side effect, increments b (which now becomes 11). The returned value (that is, 10) is assigned to a. This is what you observe, and this is the correct behaviour.
However, I expected the parentheses to have b1 incremented before its value is assigned to a1.
You aren't assigning b1 to a1: you're assigning the result of the postincrement expression.
Consider the following program, which prints the value of b when executing assignment:
#include <iostream>
using namespace std;
int b;
struct verbose
{
int x;
void operator=(int y) {
cout << "b is " << b << " when operator= is executed" << endl;
x = y;
}
};
int main() {
// your code goes here
verbose a;
b = 10;
a = b++;
cout << "a is " << a.x << endl;
return 0;
}
I suspect this is undefined behavior, but nonetheless when using ideone.com I get the output shown below
b is 11 when operator= is executed
a is 10
OK, in a nutshell: b++ is a unary expression, and parentheses around it won't ever take influence on precedence of arithmetic operations, because the ++ increment operator has one of the highest (if not the highest) precedence in C. Whilst in a * (b + c), the (b + c) is a binary expression (not to be confused with binary numbering system!) because of a variable b and its addend c. So it can easily be remembered like this: parentheses put around binary, ternary, quaternary...+INF expressions will almost always have influence on precedence(*); parentheses around unary ones NEVER will - because these are "strong enough" to "withstand" grouping by parentheses.
(*)As usual, there are some exceptions to the rule, if only a handful: e. g. -> (to access members of pointers on structures) has a very strong binding despite being a binary operator. However, C beginners are very likely to take quite awhile until they can write a -> in their code, as they will need an advanced understanding of both pointers and structures.
The parentheses will not change the post-increment behaviour itself.
a1=(b1++); //b1=10
It equals to,
uint8_t mid_value = b1++; //10
a1 = (mid_value); //10
Placing ++ at the end of a statement (known as post-increment), means that the increment is to be done after the statement.
Even enclosing the variable in parenthesis doesn't change the fact that it will be incremented after the statement is done.
From learn.geekinterview.com:
In the postfix form, the increment or decrement takes place after the value is used in expression evaluation.
In prefix increment or decrement operation the increment or decrement takes place before the value is used in expression evaluation.
That's why a = (b++) and a = b++ are the same in terms of behavior.
In your case, if you want to increment b first, you should use pre-increment, ++b instead of b++ or (b++).
Change
a1 = (b1++);
to
a1 = ++b1; // b will be incremented before it is assigned to a.
To make it short:
b++ is incremented after the statement is done
But even after that, the result of b++ is put to a.
Because of that parentheses do not change the value here.

Garbage value with post increment

Question 1
int x;
if (x++)
{
printf ("\nASCII value of X is smaller than that of x");
}
Is x assigned here with a garbage value ??
Question 2:
main ()
{
int i;
for (i = 0; i++ < 10;)
{
printf ("%d\n", i);
}
}
Can anyone explain how i++ < 10 works?I mean it should end at 9 why 10
The value of x is indeterminate, and is possibly a trap representation, in which case the behavior of x++ is undefined.
The expression i++ evaluates to the current value of i; as a side effect, the value in i is incremented. So if i == 1, the expression i++ will evaluate to 1, and as a side effect i will be set to 2.
Chapter and verse:
6.5.2.4 Postfix increment and decrement operators
...
2 The result of the postfix ++ operator is the value of the operand. After the result is
obtained, the value of the operand is incremented. (That is, the value 1 of the appropriate
type is added to it.) See the discussions of additive operators and compound assignment
for information on constraints, types, and conversions and the effects of operations on
pointers. The side effect of updating the stored value of the operand shall occur between
the previous and the next sequence point.
Emphasis mine.
In the first question, you declare x
int x;
but you do not assign it, this reserves some memory to hold the value of x, but doesn't initialize it to a known value. That's a really bad thing. Then you read it, increment it, and possibly do something.
if ( x++ ) {
printf ( "\nascii value of X is smaller than that of x" ) ;
}
Since you don't know what it's value was before you read it, it is impossible to make an educated guess as to whether your if statement will print anything.
In your second question (please one question per question), you read the value of i, then increment it, and then do the comparison on the read value. Post increment basically means, "increment the value after I read it" and so the new value will be stored, then the comparison made on the old value, and the printf statement below will print the "current, new" value.
Question 1: Yes
Question 2: Yes. i is incremented by one then compared if it's lesser than 10.

Resources