I have stumbled upon a piece of code that generates some interesting results while debugging someone else's program.
I have created a small program to illustrate this behavior:
#include <stdio.h>
int main()
{
char* word = "foobar"; int i, iterator = 0;
for (i = 0; i < 6; i++ && iterator++)
printf("%c", word[iterator]);
return 0;
}
I know that this is not the right way to print a string. This is for demonstration purpose only.
Here I expected the output to be "foobar", obviously, but instead it is "ffooba". Basically it reads the first character twice, as if the first time iterator++ is executed nothing happens.
Can anyone explain why this happens?
The thing is iterator++ actually isn't executed the first time. The ++ operator returns the current value of a variable and then increments it, so the first time through, i++ will be equal to 0. && short-circuits, so iterator++ is not executed the first time.
To fix this, you could use the comma operator which unconditionally evaluates both, rather than the short-circuiting &&.
The result of i++ is the current value of i which is zero on first iteration. This means iterator++ is not executed on first iteration due to short circuting (the right-hand side of && is only executed if the left-hand side is "true").
To fix you could use the comma operator (as already suggested or) use ++i which will return the value of i after the incremement (though comma operator is more obvious that both must always be evaluated).
You really should learn to use a debugger like e.g. gdb and to compile with warnings and debugging info like gcc -Wall -g (assuming a Linux system). A recent gcc with -Wall gives you a warning about value computed is not used before the && operation.
The increment part of your for loop is strange. It is i++ && iterator++ (but it should be i++, iterator++ instead).
When i is 0 (on the first iteration), i++ gives 0 as result, so it is false, so the iterator++ is not executed.
I am reading K&R about logic operators,let me quote the origin words of book,which can explain your question.
"Expressions connected by && or || are evaluated left to right, and
evaluation stops as soon as the truth or falsehood of the result is known."
Have a good understanding of these,the outputs wont puzzle.
Related
So, I understand that i++ increments post the condition is fulfilled, while ++i increments before the condition is fulfilled. That takes me to my question:
#include<stdio.h>
int main()
{
int i=0;
while(++i<10)
printf("%d\n",i);
return 0;
}
Now here we need the initialization of i from 0 as when it goes in the while loop, it will get incremented first, and thus it will be like while(1<10), and so it will print numbers from one to ten.
Second code:
#include<stdio.h>
int main()
{
int i=0;
while(i++<10)
printf("%d\n",i);
return 0;
}
Now since i++ increments after the value has been used, so why do we initialize i from i=0, as if it gets incremented after the comparision of value of i takes place, then why isn't 0 getting printed as well because the first loop should go like while(0<10), and not like while(1<10)? So, why is zero not getting printed?
Thank you for your time.
Yes, the first condition will evaluate to 0 < 10. You can verify that by changing it to while (i++ < 1) and see that the loop still runs (once), so clearly it's using 0 for the condition (1 < 1 would be false of course).
So why does it print 1? Because it doesn't print whichever value was used for the condition. It prints the current value of i. And the current value of i is 1 at that point because i was incremented right after it was used in the condition.
The difference of pre- and post- increment applies only to the value that the expression evaluates to.
After the evaluation of i++<10 is completed, the incrementation is also completed, and i has the value 1 in the first iteration.
printf("%d\n",i); is executed after the evaluation of i++<10, so i has the value 1 here in the first iteration.
Zero isn't printed because i is incremented right after the comparison, like this:
while(i<10) {
i += 1;
printf("%d\n",i);
}
The first sentence of your question is almost the answer:
i++ increments post the condition is fulfilled
It's incremented after the condition is checked, so i++ < 10 will increment i regardless of whether the condition ends up true or false.
The operation of ++ is not done before or after any “condition” it is in. It must be completed sometime in or around the full expression it is in. The answers that say i is updated “before” or “after” the ++i or i++ is evaluated are incorrect.
Prefix ++i does two separate things that may happen in any order:
It evaluates to the value of i after one is added.
It adds one to the stored value of i.
Postfix i++ does two separate things that may happen in any order:
It evaluates to the value of i before one is added.
It adds one to the stored value of i.
That change to the stored value of i is called a side effect. It is disconnected from the main evaluation of the expression. It can be performed before, during, or after the evaluation of i, but the evaluation still returns the pre- or post-increment value, as described above.
A full expression is one that is not contained inside another expression. So, in while (++i < 10), ++i < 10 is a full expression. The side effect can occur before any part of that is evaluated, after the value of i plus one is calculated, or after the < is evaluated. It can also occur in parts (such as updating the bytes of i one by one) during the evaluations. However, the side effect must occur after any previous full expression and before any later full expression. That is because the C standard says there is a sequence point between any two full expressions. (And there are some other rules about order of execution.)
Even if the stored value of i is updated before i++ or after ++i, the expression must still produce the value of i before or after the increment, respectively. For example, for i++, the compiler can fetch i, add one, store i, but then use the pre-add value in the expression.
The result of i++ is the value of i. As a side effect i is incremented.
The result of ++i is the value of i + 1. As a side effect i is incremented.
The statement
x = i++;
is logically equivalent to
tmp = i;
x = tmp;
i = i + 1;
with the caveat that the assignments to x and i can happen in any order, or even simultaneously (interleaved or in parallel).
Similarly, the statement
x = ++i;
is logically equivalent to
tmp = i + 1;
x = tmp;
i = i + 1;
with the same caveat as above. Again, these are logical equivalents, not what the compiler actually generates - depending on the compiler and the code involved there may not be a temporary.
In the second code, the increment will take place after the condition but before the printing statement.
Thus, the incremented value of i is printed.
This is your answer in simple language.
I saw this question in a test in which we have to tell the output of the following code.
#include<stdio.h>
int main(){
int k = 0;
while(+(+k--)!=0)
k=k++;
printf("%d\n", k);
return 0;
}
The output is -1. I am unsure why this is the answer, though.
What does the expression +(+k--) mean in C?
This code is deeply, perhaps deliberately, confusing. It contains a narrowly-averted instance of the dread undefined behavior. It's hard to know whether the person who constructed this question was being very, very clever or very, very stupid. And the "lesson" this code might purport to teach or quiz you about -- namely, that the unary plus operator doesn't do much -- is not one that's important enough, I would think, to deserve this kind of subversive misdirection.
There are two confusing aspects of the code, the strange condition:
while(+(+k--)!=0)
and the demented statement it controls:
k=k++;
I'm going to cover the second part first.
If you have a variable like k that you want to increment by 1, C gives you not one, not two, not three, but four different ways to do it:
k = k + 1
k += 1
++k
k++
Despite this bounty (or perhaps because of it), some programmers get confused and cough out contortions like
k = k++;
If you can't figure out what this is supposed to do, don't worry: no one can. This expression contains two different attempts to alter k's value (the k = part, and the k++ part), and because there's no rule in C to say which of the attempted modifications "wins", an expression like this is formally undefined, meaning not only that it has no defined meaning, but that the whole program containing it is suspect.
Now, if you look very carefully, you'll see that in this particular program, the line k = k++ doesn't actually get executed, because (as we're about to see) the controlling condition is initially false, so the loop runs 0 times. So this particular program might not actually be undefined -- but it's still pathologically confusing.
See also these canonical SO answers to all questions concerning Undefined Behavior of this sort.
But you didn't ask about the k=k++ part. You asked about the first confusing part, the +(+k--)!=0 condition. This looks strange, because it is strange. No one would ever write such code in a real program. So there's not much reason to learn how to understand it. (Yes, it's true, exploring the boundaries of a system can help you learn about its fine points, but there's a line in my book between imaginative, thought-provoking explorations versus dunderheaded, abusive explorations, and this expression is pretty clearly on the wrong side of that line.)
Anyway, let's examine +(+k--)!=0. (And after doing so, let's forget all about it.) Any expression like this has to be understood from the inside out. I presume you know what
k--
does. It takes k's current value and "returns" it to the rest of the expression, and it more or less simultaneously decrements k, that is, it stores the quantity k-1 back into k.
But then what does the + do? This is unary plus, not binary plus. It's just like unary minus. You know that binary minus does subtraction: the expression
a - b
subtracts b from a. And you know that unary minus negates things: the expression
-a
gives you the negative of a. What unary + does is... basically nothing. +a gives you a's value, after changing positive values to positive and negative values to negative. So the expression
+k--
gives you whatever k-- gave you, that is, k's old value.
But we're not done, because we have
+(+k--)
This just takes whatever +k-- gave you, and applies unary + to it again. So it gives you whatever +k-- gave you, which was whatever k-- gave you, which was k's old value.
So in the end, the condition
while(+(+k--)!=0)
does exactly the same thing as the much more ordinary condition
while(k-- != 0)
would have done. (It also does the same thing as the even more complicated-looking condition while(+(+(+(+k--)))!=0) would have done. And those parentheses aren't really necessary; it also does the same thing as while(+ +k--!=0) would have done.)
Even figuring out what the "normal" condition
while(k-- != 0)
does is kind of tricky. There are sort of two things going on in this loop: As the loop runs potentially multiple times, we're going to:
keep doing k--, to make k smaller and smaller, but also
keep doing the body of the loop, whatever that does.
But we do the k-- part right away, before (or in the process of) deciding whether to take another trip through the loop. And remember that k-- "returns" the old value of k, before decrementing it. In this program, the initial value of k is 0. So k-- is going to "return" the old value 0, then update k to -1. But then the rest of the condition is != 0 -- and it's not true that 0 != 0. That is, 0 is equal to 0, so we won't make any trips through the loop, so we won't try to execute the problematic statement k=k++ at all.
In other words, in this particular loop, although I said that "there are sort of two things going on", it turns out that thing 1 happens one time, but thing 2 happens zero times.
At any rate, I hope it's now adequately clear why this poor excuse for a program ends up printing -1 as the final value of k. Normally, I don't like to answer quiz questions like this -- it feels like cheating -- but in this case, since I fundamentally disagree with the whole point of the exercise, I don't mind.
At first glance it looks like this code invokes undefined behavior however that is not the case.
First let's format the code correctly:
#include<stdio.h>
int main(){
int k = 0;
while(+(+k--)!=0)
k=k++;
printf("%d\n", k);
return 0;
}
So now we can see that the statement k=k++; is inside of the loop.
Now let's trace the program:
When the loop condition is first evaluated, k has the value 0. The expression k-- has the current value of k, which is 0, and k is decremented as a side effect. So after this statement the value of k is -1.
The leading + on this expression has no effect on the value, so +k-- evaluated to 0 and similarly +(+k--) evaluates to 0.
Then the != operator is evaluated. Since 0!=0 is false, the body of the loop is not entered. Had the body been entered, you would invoke undefined behavior because k=k++ both reads and writes k without a sequence point. But the loop is not entered, so no UB.
Finally the value of k is printed which is -1.
Here's a version of this that shows operator precedence:
+(+(k--))
The two unary + operators don't do anything, so this expression is exactly equivalent to k--. The person that wrote this most likely was trying to mess with your mind.
This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 6 years ago.
Prog 1:
#include<stdio.h>
int main()
{
int i=0;
while(i<=8,i++);
printf("%d",i);
return 0;
}
Prog 2:
#include<stdio.h>
int main()
{
int i=0;
while(i++,i<=8);
printf("%d",i);
return 0;
}
The output of Prog 1 is 1 and that of Prog 2 is 9.
Can someone explain whats going here. How the two codes are different?
The comma operator evaluates both of its arguments in turn, throwing away the result, except for the last. The last evaluated expression determines the result of the entire expression.
i<=8,i++ - here the value of the expression is the value of i++, which is the value of i before being incremented. It's 0 so the loop immediately terminates.
i++,i<=8 - here the value of the expression is the value of i<=8 which is 0 only when i is incremented to 9.
On a personal note: I think the second form, while somewhat comparable to a for loop, is less clear to the reader of the code than an actual for loop.
1 while ( condition )
2 statement;
3 more_code();
In the above code snippet, the statement can be executed repeatedly as long as condition is true. On each iteration of the while loop, condition is evaluated to either true or false. If it's false, the while loop ends and execution continues beyond it's scope (in this case, line 4 with more_code().
We are usually accustomed to enclosing parts of code that we want to be executed in loop with curly brackets { and }, but that is not mandatory. If we do not do so, the looping code will consist of single statement, the one immediately following the while part.
It could actually be argued that the more common situation, where we combine while with curly brackets enclosed block of code could be interpreted as providing this block of code in place of a single statement, with braces providing information that the block should be treated (by compiler analysing it's relation with preceding and following code) as if it was a single statement.
However, as it is perfectly valid to provide a single statement, not a usual block of code, it's worth to understand that there is a valid statement that is empty. We get an empty statement by typing a semicolon without preceding it with a code causing anything. So following is perfectly valid:
1 code;
2 ; // empty statement
3 ; // another empty statement
or in fact this:
1 code;; // a "code" statement followed by empty statement in the same line
The while( condition ) part is not terminated with a semicolon, so if it's supposed to control some actual code (apart from condition), it should not be followed by a semicolon. If it is immediately followed by a semicolon, that semicolon will constitute (and be so interpreted by compiler) an empty statement, so the looping code will be empty. If that's unintended, then the code we wanted to be looped, whether a block of code or a statement, will not be looped, but rather executed once, after (and if) loop ends.
1 int a = 0;
2 while ( a < 3 ) ; // Next line is not part of loop - only the empty statement this semicolon creates is. This loop is infinite, or in other words it will never end.
3 a++; // This won't be executed even once.
4 printf("This never happens.");
(It's worth realizing that lines are only important for us, humans, in C. Lines and indentation can be misleading if they represent the intentions of programmer, when he failed to write the code functioning as he wanted it to.)
Therefore what happens in both snippets from the question, is we get condition evaluated continuously until it yields false. To understand what's going on we need to examine the way comma operator works.
(Note, while comma as a character can be used with a completely different meaning in various places in C - I can think of function declarations, definitions and calls - in this case comma character is part of condition, therefore it acts as an operator - something akin to + or % operators.)
expression1 , expression2
Comma operator causes expression1 to be evaluated first, then expression2, and returns the value of expression2.
Upon every evaluation of condition, we will thus evaluate both expressions, (in this case both being operands, i++ and i<=8), then consider value of the right one as result of comma operand itself, and thus as value of our condition. So the loop will keep repeating as long as the right operand resolves as true.
While usually we use condition to control the execution of loop, often, as in this case, condition may have "side" effects (intentional or unintended). In our case variable i is affected by every evaluation of condition: it is increased by one.
Our example differs only in order of operands of condition, therefore pay attention to the right operand which really controls the execution of the loop.
Let's examine the second example first. In this case we have condition i++, i<=8. This means upon every evaluation we first increase i, then check if it's less than or equal to 8. So on first evaluation of condition we will increase i from 0 to 1 and conclude that 1<=8, so the loop continues. The loop so constructed will break when i becomes 9, ie. on the 9th iteration.
Now as for the first example, the condition is i<=8, ++i. Since comparison has no side effects, that is we could perform any number of comparisons in any order and if that's the only thing we did, that is if we did not perform any other action in a way or order dependent of results of the comparisons, those comparisons would do absolutely nothing. As is in our case, we evaluate i<=8 which evaluates to true or false, but we make no use of this result, just proceed to evaluating the right operand. So left operand absolutely doesn't matter. Right operand, on the other hand, has both a side effect and it's value becomes value of entire condition. Before each loop iteration we check if i++ evaluates to true or false.
i++ is a unary operator of post-incrementation. It returns value of i then increases it by one (the difference between i++ and ++i is subtle but crucial in cases like this one). So what happens is we first check whether i is true or false, then i is increased by one.
In C there is no boolean type. Integers are considered to be true if they have a non-zero value.
So upon first evaluation of i++ we get 0, that is false. This means the loop is broken without even a single iteration. However it does not break evaluation of i++, which causes i to increase by one before we're done with the loop and execution proceeds beyond it. So once we're done with the while loop, i is already 1.
If we want to be very precise in our understanding, the part where we take the result of evaluating entire condition happens, chronologically, after we are finished executing any code involved in this evaluation. So we first memorize that i was 0 at the point we got toward i++ part, then we increase i by one, and then we are finished executing condition, so we provide value of 0 to the code that decides if we should do another (in this case first) iteration or jump beyond looping part and move on. This is exact reason why everything within condition will actually happen even though the fact that loop will end was already determined: it was determined, but it was not checked and acted upon until condition finishes executing.
The expression separator operator , forces evaluation from left to right, and is also a sequencing point.
Prog 1: consider i <= 8, i++. i <= 8 is evaluated and discarded then i++ is evaluated. The entire expression has the unincremented value of i. Since i is initially 0, the while loop terminates on the first iteration. The output will be that singly incremented value of i, i.e. 1.
Prog 2: i++ is evaluated and the result discarded, then i <= 8 is evaluated with the new value of i since , is a sequencing point. So the while loop runs until i <= 8 is no longer true with the incremented value of i. The output will be 9.
I'm just learning some C, or rather, getting a sense of some of the arcane details. And I was using VTC advanced C programming in which I found that the sequence points are :
Semicolon
Comma
Logical OR / AND
Ternary operator
Function calls (Any expression used as an argument to a function call is finalized the call is made)
are all these correct ?. Regarding the last one I tried:
void foo (int bar) { printf("I received %d\n", bar); }
int main(void)
{
int i = 0;
foo(i++);
return 0;
}
And it didnt print 1, which according to what the VTC's guy said and if I undertood correctly, it should, right ?. Also, are these parens in the function call the same as the grouping parens ? (I mean, their precedence). Maybe it is because parens have higher precedence than ++ but I've also tried foo((i++)); and got the same result. Only doing foo(i = i + 1); yielded 1.
Thank you in advance. Please consider that I'm from South America so if I wasnt clear or nothing makes sense please, oh please, tell me.
Warmest regards,
Sebastian.
Your code is working like it should and it has nothing to do with sequence points. The point is that the postfix ++ operator returns the non-incremented value (but increments the variable by 1 nonetheless).
Basically:
i++ – Increment i by one and return the previous value
++i – Increment i by one and return the value after the increment
The position of the operator gives a slight hint for its semantics.
Sequence means i++ is evaluted before foo is invoked.
Consider this case (I am not printing bar!):
int i = 0;
void foo (int bar) { printf("i = %d\n", i); }
int main(void){
foo(i++);
return 0;
}
i = 1 must be printed.
C implements pass-by-value semantics. First i ++ is evaluated, and the value is kept, then i is modified (this may happen any time between the evaluation and the next sequence point), then the function is entered with the backup value as the argument.
The value passed into a function is always the same as the one you would see if using the argument expression in any other way. Other behavior would be fairly surprising, and make it difficult to refactor common subexpressions into functions.
When you do something like:
int i = 0, j;
j = i++;
the value of i is used first and then incremented. hence in your case the values of i which is 0 is used (hence passed to your function foo) and then incremented. the incremented values of i (now 1) will be available only for main as it is its local variable.
If you want to print 1 the do call foo this way:
foo(++i);
this will print 1. Rest you know, why!
#include <stdio.h>
main()
{
int i;
for(i=0; i<0, 5; i++)
printf("%d\n", i);
}
I am unable to understand the i<0, 5 part in the condition of the for loop.
Even if I make it i>0, 5, there's no change in output.
How does this work?
On topic
The comma operator will always yield the last value in the comma separated list.
Basically it's a binary operator that evaluates the left hand value but discards it, then evaluates the right hand value and returns it.
If you chain multiple of these they will eventually yield the last value in the chain.
As per anatolyg's comment, this is useful if you want to evaluate the left hand value before the right hand value (if the left hand evaluation has a desirable side effect).
For example i < (x++, x/2) would be a sane way to use that operator because you're affecting the right hand value with the repercussions of the left hand value evaluation.
http://en.wikipedia.org/wiki/Comma_operator
Sidenote: did you ever hear of this curious operator?
int x = 100;
while(x --> 0) {
// do stuff with x
}
It's just another way of writing x-- > 0.
Comma operator evaluates i<0 Or i>0 and ignores. Hence, it's always the 5 that's present in the condition.
So it's equivalent to:
for(i=0;5;i++)
The coma operator is done to the initialization and to the increment part, to do something like for(i=0,j=20;i<j;i++,j--), if you do it in the comparation part it will evaluate the last one (as it was already answered before)
i<0,5 will always evaluate to 5, as always the right expression will be returned for ex1,ex2 .
The comma operator is intended for cases where the first operand has some side effects. It's just an idiom, meant to make your code more readable. It has no effect on the evaluation of the conditional.
For example,
for (i = 0; i<(i++, 5); i++) {
// something
}
will increment i, and then check if i<5.