2014-05-10 121 views
0

這是從虛擬機實驗中刪除的一小段代碼。 它應該從一個字節緩衝區推入並彈出雙精度。 但是,它顯示了一些非常有趣的行爲......特別是,它使得printf以相反的順序打印它的參數,至少在使用MinGW g ++ 4.8.1進行編譯時。 發生了什麼事? O_o指針操作導致printf以相反順序打印參數?

#include <stdio.h> 

#define STACK_BYTES (1024 * 1024 * 2) 

struct VM { 
    uint8_t* stack; 
    uint8_t* sp; 

    VM() 
    { 
     stack = new uint8_t[STACK_BYTES]; 
     sp = stack; 
    } 

    ~VM() 
    { 
     delete[] stack; 
    } 

    void pushv(double val) 
    { 
     *(double*)sp = val; 
     sp += sizeof(double); 
    } 

    double popv() 
    { 
     sp -= sizeof(double); 
     return *(double*)sp; 
    } 
}; 

int main() 
{ 
    VM vm; 

    vm.pushv(666.f); 
    vm.pushv(777.f); 
    vm.pushv(888.f); 

    printf("%f ", vm.popv()); 
    printf("%f ", vm.popv()); 
    printf("%f\n", vm.popv()); // 888.000 777.000 666.000, as expected. 

    printf("SP: %d\n", (int)(vm.sp - vm.stack)); // SP: 0, as expected. 

    vm.pushv(666.f); 
    vm.pushv(777.f); 
    vm.pushv(888.f); 

    printf("%f %f %f\n", vm.popv(), vm.popv(), vm.popv()); // 666.000 777.000 888.000??? 

    return 0; 
} 

回答

1

該標準沒有規定任何評估參數的順序。你的代碼是不確定

printf("%f %f %f\n", vm.popv(), vm.popv(), vm.popv()); 

月有不同的結果在不同的編譯器實現。你的第一個版本更好。

0

編譯器將參數從最後一個傳遞給printf函數,並將它們從最後一個接一個地推到堆棧上。
如果訂單有問題,請使用中間變量。

+0

我認爲這是錯誤的_「從最後一個...」。標準不會說這樣的事情。 – deepmax

+0

它依賴於編譯器,但顯然在這種情況下,他的編譯器是從最後一個編譯器開始編譯的。 –

+0

我現在明白了。功能參數評估順序不能被依賴。這同樣適用於二元運算符的操作數,例如+? – user3026691