-5

Hi folks i tried to program a simple switch statement and stuck uppon this problem. I cant figure out why this code works correctly, i guess it is because the precedence of the operators ** and ++. If this is the case ill be happy if someone can write an example how should i use value-at * and inc/dec operator in a statement like below.

Thanks in advance,

while (--argc > 0) 
        argv++;
        switch (**argv) 

and this code dont

while (--argc > 0) 
        switch (**(argv++)) 

Full code:

while (--argc > 0) {
        switch (**(argv++)) {
        case '\0':
            panic("empty command line argument");
            break;
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            push (atof(*argv));
            break;
        case '+':
            push(pop() + pop());
            break;
        case '-':
            op2 = pop();
            push(pop() - op2);
            break;
        case '*':
            push(pop() * pop());
            break;
        case '/':
            op2 = pop();
            push(pop() / op2);
            break;
        default:
            panic("unknown command");
            break;
        }
    }
igal
  • 3
  • 2

2 Answers2

2

Using the postincrement on a given variable in any expression causes the variable to increment after the expression has been evaluated.

As stated by your first, working code, where you increment argv value before getting it's referenced value in the switch, you want the variable to be incremented before your expression is evaluated, so you need to use the preincrement:

while (--argc > 0) 
        switch (**(++argv)) 
Manuel Miranda
  • 823
  • 5
  • 13
  • That is bad code - human cognitive limits restrict the number of things a human mind can track at any one time to about 5 to 7 things. All those operators stuffed into two lines makes for nasty bugs that are all but impossible to figure out. See https://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two – Andrew Henle Sep 09 '15 at 09:53
  • I agree with you, but it's the structure that the OP requested and it's not my job here to guess why or why not he does need it like this. – Manuel Miranda Sep 09 '15 at 09:55
  • The inner parentheses are redundant. – EOF Sep 09 '15 at 10:03
  • @ManuelMiranda Thanks a lot Manuel, i've confused my self and didn't pay attention to this little detail, thanks. – igal Sep 09 '15 at 10:18
0

I think you are being confused by the parentheses. Parentheses affect the order of evaluation, but you are using post increment, which is applied at the end, no matter what order the operators are evaluated.

In your first snippet the order is clear: first you increase argv, then you dereference it. That is, you dereference the "next" element, not the current one.

In your second snippet you want to achieve the same result, and you are playing with parentheses. This is not the solution. Parentheses affect the order in which the 2 operators (++ and **) are evaluated, but this doesn't mean the effects are applied in that order.

For example: if you wrote

switch ((**argv)++)

the compiler would apply ** first, dereferencing it, giving you the content, and then it would apply ++ on it (obviously argv must be a data type which can be increased or there will be an error, but it doesn't matter here). Instead, if you write, as you did,

switch (**(argv++))

the increment (++) is applied first, and then the indirection (**). But here is the trick: post increment is still post increment. Applying the post increment here means: take the current value, and when everything is finished remember to increase it. So argv is used as it is, without increasing it (yet), and sent to **, which will give the current value (not the next one!). Then, after switch has read the current element, argv is increased (post-increment), so that if your cases printed **argv you would notice it's the "next" value.

A solution is using pre-increment:

switch (**(++argv))

but if you ask me, the real solution is to avoid these headaches entirely and write the code in 2 separate lines, so that it's immediately obvious what happens. As you did in your first snippet. This is the most readable style, and therefore should be the preferred choice. Then you can forget about everything: order of evaluation, parentheses, pre- vs post-increment, associativity.

  • Remove redundant inner parentheses for even more succinct code. – EOF Sep 09 '15 at 10:03
  • 1
    @EOF removing the parentheses would indeed delete some clutter, but then it would be harder to understand in which order the operators are evaluated. I think all in all it would be *less* readable. – Fabio says Reinstate Monica Sep 09 '15 at 10:10
  • The OP probably wouldn't have asked the question if he didn't want shorter code. I feel he should get his wish (however questionable it may be). – EOF Sep 09 '15 at 10:13