2014-05-10 52 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