+(+k--) expression in C

后端 未结 3 1434
你的背包
你的背包 2021-01-17 19:06

I saw this question in a test in which we have to tell the output of the following code.

#include

int main(){
    int k = 0;
    while(+(+k--         


        
相关标签:
3条回答
  • 2021-01-17 19:18

    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.

    0 讨论(0)
  • 2021-01-17 19:23

    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.

    0 讨论(0)
  • 2021-01-17 19:42

    [For the record, I have edited this answer pretty significantly since it was accepted and voted on. It still says basically the same things, though.]

    This code is deeply, perhaps deliberately, confusing. It contains a narrowly-averted instance of the dread undefined behavior. It is basically impossible to determine 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 certainly not an important enough one 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:

    1. k = k + 1
    2. k += 1
    3. ++k
    4. 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, ever write such code in a real program. So there's no reason to learn how to understand it. (Yes, its true, exploring the boundaries of a system can help you learn about its fine points, but there's a pretty clear line in my book between imaginative, thought-provoking explorations versus dunderheaded, abusive explorations, and this expression is very 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:

    1. keep doing k--, to make k smaller and smaller, but also
    2. 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 -- but as we just saw, the first time we tested the condition, we got a 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 so vociferously disagree with the whole point of the exercise, I don't mind.

    0 讨论(0)
提交回复
热议问题