walshrm
walshrm

Reputation: 25

While conditions followed by ;

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?

Upvotes: 1

Views: 144

Answers (5)

Useless
Useless

Reputation: 67713

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.

Upvotes: 0

Nik Bougalis
Nik Bougalis

Reputation: 10613

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.

Upvotes: 1

K Scott Piel
K Scott Piel

Reputation: 4380

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

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409146

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.

Upvotes: 2

Daniel Fischer
Daniel Fischer

Reputation: 183883

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.

Upvotes: 2

Related Questions