Search code examples
c++stackpostfix-notation

Postfix negative is incorrect and communative


So I'm evaluating Postfix expressions using a stack. The expression 10 6 - reads as 10 - 6 infix and should equal 4. But it doesn't, it equals -4. Worse, even when I try to reverse the code, it still equals -4. I'm not sure if this is something wrong with my stack, or the function calls, or some quirk of C++. However, if I store 1 popped value off the stack in a variable and then do the equation, it works fine.

Relevant code: Stack class

template <class Item>
class stack {
private:
    struct node {
        Item item;
        node* next;
        node(Item x, node* t) {
            item = x;
            next = t;
        }
    };
    typedef node* link;
    link head;

public:
    stack(int) { head = 0; }
    int empty() const { return head == 0; }
    void push(Item x) { head = new node(x, head); }
    Item pop() {
        Item v = head->item;
        link t = head->next;
        delete head;
        head = t;
        return v;
    }
};

Evalutating the negative operation

    else if (argv[i][0] == '-') {
    stck.push(((-1) * stck.pop()) + stck.pop()); // A-B = -B+A
    // stck.push(stck.pop()+((-1)*stck.pop())); //A-B = -B+A
} // Both equations equal the same thing (Note I dont use both at the same
  // time)

This works

int n = (stck.pop());
stck.push(-1*n+stck.pop()); //A-B = -B+A

Solution

  • Yes this is a "quirk of C++": the order in which the arguments in this specific expression are evaluated is undefined. It's weird how you get the same result twice, but you should generally not assume those pops are evaluated left-to-right!

    From the linked article, section "Hidden Dependencies":

    x = f() + g() + h();

    Is there any doubt about what will happen? At first sight it appears as though nothing could go wrong here. The 3 functions will be called in indefinite order, the sum of their return values will be calculated and an assignment will be performed. But, what if all 3 functions would access a shared static or global variable that they read and modify? We do not know in which order the 3 functions will be invoked and for that reason we would not know in which order read and write access to the shared data would be performed. Again, another sequence point challenge.

    Solution: use temporary variables.