C语言函数入参压栈顺序为什么是从右向左?

看到有人提问到,在处理printf/cout时,压栈顺序是什么样的?大家都知道是从右往左,也就是说从右往左的计算,但是,这里的计算不等于输出。

a++和++a的压栈的区别:在计算时,遇到a++会记录此时的a的值作为最后的输出结果。遇到a和++a的时候则不会将此时的计算结果作为最终的输出,只会修改a的值,在最终输出的时候都输出a的值(所以++a和a的结果总是一样的)。

比如:

    int a = 2;
        cout << ++a << a++ << a << ++a << a++ << a << ++a << endl;

 输出为:7 5 7 7 3 7 7

但是不禁要问,为什么C语言的函数调用入参压栈顺序一定是自右向左?反过来不可以吗?

首先,在函数调用过程中,最先入栈的是调用函数调用处的下一条指令的地址,这样调用完成后返回到该地址继续执行,这个地址是很重要的,然后才是函数的入参,函数的内部局部变量。调用结束,将栈内容一一出栈,最后栈顶指向了开始存储的指令地址,主函数继续从这里开始还行。

其次,函数调用入参的入栈顺序和C语言支持变长参数有关,比如printf函数就支持变长参数,也即void printf(const char *fmt,……),这个时候并不知道参数有多少个,如果从左向右入栈,那么fmt就在栈底,该参数的位置无法通过栈顶指针偏移来确定,因为不知道栈顶和栈底之间有多少个参数,大小是多少,无法确定,但是,如果从右向左入栈的话,fmt参数就在栈顶的位置,通过这个固定的普通参数就可以通过偏移逐一寻址到后续参数的地址。