指针操作导致printf以相反顺序打印参数



下面是从虚拟机实验中删除的一小段代码。它应该从字节缓冲区中push和pop double。然而,它表现出一些非常有趣的行为……具体来说,它以某种方式使printf以相反的顺序打印其参数,至少在使用mingw++ 4.8.1编译时是这样。这是怎么呢O_o

#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("%fn", vm.popv()); // 888.000 777.000 666.000, as expected.
    printf("SP: %dn", (int)(vm.sp - vm.stack)); // SP: 0, as expected.
    vm.pushv(666.f);
    vm.pushv(777.f);
    vm.pushv(888.f);
    printf("%f %f %fn", vm.popv(), vm.popv(), vm.popv()); // 666.000 777.000 888.000???
    return 0;
}

标准没有规定参数的求值顺序。你的代码是未指定:

printf("%f %f %fn", vm.popv(), vm.popv(), vm.popv());

在不同的编译器实现中可能有不同的结果。你的第一个版本更好。

编译器从上一个传递给printf函数的形参中计算值,从上一个依次将它们压入堆栈。
如果顺序有问题,请使用中间变量。

最新更新