I have been asked to comment some code and describe what it does. All was fine and I had a good handle on what was being done in the the cases of the switch but now I am unsure whether any of the cases are ever met. I don't have anyway to run or test this code currently as my main machine with all my regular software is down.
Does either of the cases of the switch get used besides the default with the conditions of this while loop? is i simply incremented to 32 and the rByte returned before it even makes the switch? What is with the ; after the conditions of the while? Shouldn't it be followed by {....} rather than ; ?
while(pCommand[--Ptr.Five] > 10 && ++i <32);
if(i==32)
{
return rByte;
}
switch(pCommand[Ptr.Five++])
{
case 2: ... (lots of code)
break;
case 4: ... (lots of cod)
break;
default: ...
break;
}
Also, how is the --Ptr.Five handled vs. the Ptr.Five++? My understanding is the first moves the pointer back and uses that value while the second uses the current value and post increments.
Am I missing something? Even moving past the ; after the conditions of the while and the lack of {} after the while, wouldnt the value of Ptr.Five be > 10 and therefore never be 2 or 4 ever?
With the ; behind the conditions of the while, would i just get bumped to32 and the following if would return the rByte?
The loop
while(pCommand[--Ptr.Five] > 10 && ++i <32);
decrements Ptr.Five and increments i until
pCommand[Ptr.Five] <= 10, or
i >= 32,
whichever happens first. Since the changes to the interesting variables are done in the loop condition, the loop body should be empty. (Not that it's particularly good style, but I've seen worse.)
If i == 32, the switch isn't reached, otherwise, if i < 32, you know that pCommand[Ptr.Five] <= 10, so both non-default cases can be reached.
The semicolon by itself is an empty statement. So doing e.g.
while (complicated_expression)
;
Is the same as:
while (complicated_expression)
{
}
It's often used when complicated_expression has side-effects, so no loop body is needed.
It's impossible to answer your question. Even if we assume that i starts at 0, who knows what value pCommand[Ptr.Five] has at the start of this code block?
Addressing some of the questions that can be answered, would it help if we rewrote the while like this:
while(pCommand[--Ptr.Five] > 10 && ++i <32)
{
/* do nothing as the body of the loop... nothing at all.
* Everything happens in the condition.
*/
}
The syntax with the semicolon is valid, if a bit confusing at first: think of what the semicolon means in C/C++ (terminates a statement) and then think of what the statement being terminates is in this case (hint: it's a "no operation").
The difference between --Ptr.Five and Ptr.Five-- is what you describe: the first variant (the pre-decrement) will decrement Ptr.Five and then return the resulting value; the second variant (the post-decrement) will decrement the Ptr.Five but return the value before the decrement.
while(pCommand[--Ptr.Five] > 10 && ++i <32);
doesn't have a body, but the loop condition itself has side-effects, so it does do something.
We could re-write this as:
while (1) {
--Ptr.Five;
if (pCommand[Ptr.Five] <= 10)
break;
++i;
if (i == 32)
break;
}
if (i == 32) {
/* we never hit the pCommand condition */
}
As for why:
it searches backwards through pCommand, from offset Ptr.Five to at most 32 entries earlier, looking for a value <= 10
if it doesn't find such a value within 32 entries, it returns rByte
if it does find such a value, it switches on it and does some work
PtrFive is incremented to indicate the next entry after this value, after the switch is dispatched
Also, how is the --Ptr.Five handled vs. the Ptr.Five++? My understanding is the first moves the pointer back and uses that value while the second uses the current value and post increments.
That's exactly correct. In:
pCommand[--Ptr.Five] > 10
Ptr.Five is decremented before the rest of the expression is evaluated, whereas in:
pCommand[Ptr.Five++]
the expression is evaluated with the old value of Ptr.Five, and then it's incremented right after. Here, that means the switch is based on the old entry in pCommand (the one that ended the while loop because it's <= 10), but Ptr.Five is incremented before code inside the cases executes.
A quick note on side-effects: as John Bode points out in a comment, my description of the pre-decrement and post-increment expressions isn't quite accurate.
This is because storing the new value into Ptr.Five doesn't have to happen right away.
However since it does have to happen (as if) by the next sequence point, which is here the &&, there's no real ambiguity.
This generally only becomes an issue if you string multiple interdependent side-effecting expressions together in a single statement. So, you know, try and avoid that.
Presuming i started at 0 -- The while loop is parsing through 31 elements (1-31) of the pCommand array, decrementing Ptr.Five before checking the value, looking for a value that is less than 10. If it does not find one, the function returns rByte -- it then checks the value of pCommand[Ptr.Five] before it increments... therefore, the value used in the switch is the same as the value used in the while conditional. The value could well be any of the switch conditions as we know it is less than 10
Related
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.
I have to rewrite this for loop into a do while loop, but I can't figure out what this does. Please help
for(;; done = (int) sum == 5
{if (done) break;
sum += 2.6;}
Let's assume that the syntax error is resolved, so that the code reads
for(;; done = (int) sum == 5)
{
if (done) break;
sum += 2.6;
}
Now this code works as follows: the for loop has no initialization expression and no test expression, so it begins execution unconditionally. The first thing that happens is the "flag" done (an undefined object that I'm assuming is an int that may or may not be initialized to zero) is checked. If it's true (non-zero), the code breaks out of the for loop. if not, 2.6 (a double) is added to sum (an undefined object that I'm assuming is a double and that may or may not be initialized to a sensible value, or a number at all). When execution reaches the closing brace, the iteration statement in the for loop is executed, which compares sum to 5 (after converting sum to an integer value), and assigns the result of the comparison (i.e. 1 for true and 0 for false) to done.
Converting this to a while loop ought to be fairly straightforward. Simply execute these steps in order. Note that since the first piece of code to execute is checking if(done), the code more naturally lends itself to a simple while than a do-while loop.
Note that this would have been considerably clearer if you had defined the types of your variables, and provided initial values for them.
Let's consider the following C code snippet.
while(!var_can_be_0_or_1 && foo_returns_0_or_1(arg1, arg2)) {
body;
}
it's a simple while condition statement which does what I am failing to understand. But let's say I have two macros
#define TRUE 1
#define FALSE 0
Can someone please tell me(or rather explain to me) what are we checking under the condition in this while loop here? I mean in what condition/s the loop body will execute and in which condition/s it will skip?
Elaboration
I found it in a book about Data Structures in a program which converts an infix expression string into a postfix one. The exact code was something like this --->
int prcd(char char);
int und, outpos;
char symb, topsymb;
while(!und && prcd(topsymb, symb)) { <----- Stuck on this one real bad
postr[outpos++] = topsymb;
popandtest(&opstk, &topsymb, &und);
}
The elaboration is probably unnecessary but just to put things into context.
;)
EDIT :
I'm really sorry if the question was somewhat unclear to people who are trying to help, so I'll explain a little bit more about what I am really asking here
Let's forget the code I wrote in the elaborate portion of this text and go back to the first one and let's just say we have a while loop , plain and simple while loop
while(!condition1 && condition2) {
execute some codes;
}
Here, condition1 = und, und is an int whose value can be either 0 or 1(and NOTHING ELSE). 0 and 1 are macroed to FALSE and TRUE respectively. And condition2 = prcd(topsymb, symb) ; it's a function whose prototype is mentioned as int prcd(char char);. Again it returns either 0 or 1 and NOTHING ELSE.
Now what I want to know is how the condition inside the while loop brackets gets evaluated.
Hope this clears things up. :)
I mean in what condition/s the loop body will execute and in which
condition/s it will skip
body will execute if var_can_be_0_or_1 is false (i.e. 0) AND the return value of the function foo_returns_0_or_1 is true (i.e. not 0).
If either criteria are not met then body will be skipped.
I am unsure if this is what you are looking for, but here is what I believe you want:
while(!var_can_be_0_or_1 && // if this is '0', continue; else exit
foo_returns_0_or_1(a, b) // if this is NOT '0', continue; else exit
Does this help?
Using your macros, this is similar to writing
while (var_can_be_0_or_1 == FALSE && foo_returns_0_or_1 == TRUE)
I say similar because, if the function foo_returns_0_or_1 does NOT return a 1, but instead returns some other number, then your TRUE macro will not match, and the condition test will fail, as written above.
C does not require you to write the equality (== TRUE), but rather can evaluate on the output of the function or the state of the variable, if it is an int, and is the better choice for this statement.
As #John Bode notes, if the first condition fails, then the second condition will never be tested. Since this is a function, then it is possible that the function will never be called.
The && operator forces left-to-right evaluation. !var_can_be_0_or_1 will be fully evaluated (and any side effects applied); if the result of the expression is non-zero (true), then foo_returns_0_or_1(arg1, arg2) will be evaluated. If the result of that expression is also non-zero (true), then the body of the loop will be executed, otherwise the loop will exit.
I think this is some pseudo code with missing pre conditions, because it won't compile as is.
if 'und' is global then it must be initialized to zero and the while loop will always be TRUE, if inside function this must be initialized with garbage because it is allocated on stack and hence the behavior is unpredictable.
Similarly, missing definition of prcd(), it is hard to suggest what it returns.
I think your need to correct the question with proper inputs.
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 saw this code today :
if(++counter == 10)
{
//Do Something
foo();
}
I think this is bad style, but, is the execution compiler dependent aswell? say the counter is set to 8 before we get to this line, it's going to increment it, then compare 10 to 8, the value before, or compare 10 to 9, the value of counter after it got incremented?
What do you think SO? Is this common practice? bad style?
There's nothing compiler-dependent in the behavior of this code (besides possible overflow behavior). Whether it is a good style is a matter of personal preference. I generally avoid making modifications in conditionals, but sometimes it can be useful and even elegant.
This code is guaranteed to compare the new value to 10 (i.e. 9 is compared to 10 in your example). Formally, it is incorrect to say that the comparison takes place after counter gets incremented. There's no "before" or "after" here. The new value can get pre-calculated and compared to 10 even before it is physically placed into counter.
In other words, the evaluation of ++counter == 10 can proceed as
counter = counter + 1
result = (counter == 10)
or as
result = ((counter + 1) == 10)
counter = counter + 1
Note that in the first case counter is incremented before the comparison, while in the second case it is incremented after the comparison. Both scenarios are valid and perfectly possible in practice. Both scenarios produce the same result required by the language specification.
Operator precedence will always cause the increment to take place before the comparison. You may use parenthesis if you wish to make this very explicit, but I wouldn't call this bad coding style.
Personally I'd always separate this into two statements.
counter++;
if (counter == 10)
DoSomething();
This way you don't need to think about what order things happen—there is no scope for confusion. It makes no difference to the generated code and when that is so, readability and maintainability concerns are always king.
It is well defined by the language standard, and whether it is a bad style or not is a matter of a personal preference, and of a context as well. I have one function using conditions similar to this, which I think looks and works very nice, and which I think would be less readable when the increment would be taken out of the condition.
const char *GetStat(int statId)
{
int id = 0;
if (statId==id++)
{
return "Buffers";
}
else if (statId==id++)
{
return "VBuffers";
}
#ifndef _XBOX
else if (statId==id++)
{
return "Reset factor";
}
#endif
else if (statId==id++)
{
return "CB Mem";
}
return "";
}
Note: the increments are actually not "performed" at all here, a decent compiler will eliminate the ++ done on id variable into constants.