看到面试题C语言中函数参数的入栈顺序如何?

自己不知道,边上网找资料。下面是详细解释

#include <stdio.h>

void foo(int x, int y, int z)
{
        printf("x = %d at [%X]/n", x, &x);
        printf("y = %d at [%X]/n", y, &y);
        printf("z = %d at [%X]/n", z, &z);
}

int main(int argc, char *argv[])
{
        foo(100, 200, 300);
        return 0;
}

运行结果: 
x = 100 at [BFE28760]
y = 200 at [BFE28764]
z = 300 at [BFE28768]

C程序栈底为高地址,栈顶为低地址,因此上面的实例可以说明函数参数入栈顺序的确是从右至左的。可到底为什么呢?查了一直些文献得知,参数入栈顺序是和具体编译器实现相关的。比如,Pascal语言中参数就是从左到右入栈的,有些语言中还可以通过修饰符进行指定,如Visual C++。即然两种方式都可以,为什么C语言要选择从右至左呢?

进一步发现,Pascal语言不支持可变长参数,而C语言支持这种特色,正是这个原因使得C语言函数参数入栈顺序为从右至左。具体原因为:C方式参数入栈顺序(从右至左)的好处就是可以动态变化参数个数。通过栈堆分析可知,自左向右的入栈方式,最前面的参数被压在栈底。除非知道参数个数,否则是无法通过栈指针的相对位移求得最左边的参数。这样就变成了左边参数的个数不确定,正好和动态参数个数的方向相反。

因此,C语言函数参数采用自右向左的入栈顺序,主要原因是为了支持可变长参数形式,C语言中可变参数都是从左到右,所以不管你有多少个参数反正将最右面的那个压入栈底,最左面的参数出入栈顶。换句话说,如果不支持这个特色,C语言完全和Pascal一样,采用自左向右的参数入栈方式

博文选自C语言参数的入栈的顺序

c语言中函数参数入栈的顺序是什么?为什么的更多相关文章

  1. x86汇编寄存器,函数参数入栈说明

    https://en.wikipedia.org/wiki/X86_calling_conventions

  2. C语言中可变参数函数实现原理

    C函数调用的栈结构 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈.例如,对于函数: void fu ...

  3. c++参数入栈顺序和参数计算顺序

    关于 本文涉及到代码,演示环境为:win10 + VS2017 ,ubuntu+clang clang版本: 参数入栈顺序 顺序 几种常见的函数参数入栈顺序,还有两种就不介绍了(__clrcall._ ...

  4. C语言中可变参数的函数(三个点,“...”)

    C语言中可变参数的函数(三个点,“...”) 本文主要介绍va_start和va_end的使用及原理. 在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end ...

  5. C语言中可变参数的原理——printf()函数

    函数原型: int printf(const char *format[,argument]...) 返 回 值: 成功则返回实际输出的字符数,失败返回-1. 函数说明: 使用过C语言的人所再熟悉不过 ...

  6. C语言中的堆与栈20160604

    首先声明这里说的是C语言中的堆与栈,并不是数据结构中的!一.前言介绍:C语言程序经过编译连接后形成编译.连接后形成的二进制映像文件是静态区域由代码段和数据段(由二部分部分组成:只读数据 段,未初始化数 ...

  7. C语言中函数参数传递

    C语言中函数参数传递的三种方式 (1)值传递,就是把你的变量的值传递给函数的形式参数,实际就是用变量的值来新生成一个形式参数,因而在函数里对形参的改变不会影响到函数外的变量的值.(2)地址传递,就是把 ...

  8. c语言中函数的简单介绍

    c语言中函数的介绍: 函数,简单的说就是代码的打包.存放在一个地方,当需要的时候调用. 函数分类: 1.无参无返回值函数 void func() 2.无参有返回值函数  int func() 3.有参 ...

  9. C语言中函数返回字符串的4中方法

    C语言中函数返回字符串的4中方法 函数的构成部分:返回类型.函数名称.参数.函数主体 参数:函数调用时传入的参数称为实参,函数定义时出现的参数为形参 形参的作用在于接收实参传入的值,形参和函数内部的其 ...

随机推荐

  1. erlang 大神

    http://blog.csdn.net/erlib/article/details/46655905

  2. AIR:使用 HTML + Javascript 开发桌面应用

    背景 断断续续用Winform和WPF开发过一些小工具,始终不得其法门,在玩Flex的时候就接触过AIR,最近发现可以用HTML + Javascript开发AIR应用,本文就尝试一下(Hello,W ...

  3. 第十一章 PhpMyAdmin连接远程mysql服务器---连接openwrt 703N服务器

    //千万不要在你原来的那个phpmyadmin文件夹上操作~~~要复制一个新的进行操作,这样我们就可以同时使用本地和远程   一.下载phpmyadmin到本地 我使用的是windows下的集成WAM ...

  4. [Linux] Ubuntu下解压rar文件的方法

    一般通过默认安装的ubuntu是不能解压rar文件的,只有在安装了rar解压工具之后,才可以解压.其实在ubuntu下安装rar解压工具是非常简单的,只需要两个步骤就可以迅速搞定. ubuntu 下r ...

  5. Java效率工具之Lombok

    参考: http://www.54tianzhisheng.cn/2018/01/09/lombok/ https://zhuanlan.zhihu.com/p/32779910

  6. DICOM:DICOM三大开源库对比分析之“数据加载”

    背景: 上一篇博文DICOM:DICOM万能编辑工具之Sante DICOM Editor介绍了DICOM万能编辑工具,在日常使用过程中发现,“只要Sante DICOM Editor打不开的数据,基 ...

  7. UVA 10790 (13.08.06)

     How Many Points of Intersection?  We have two rows. There are a dots on the toprow andb dots on the ...

  8. Drupal、IoT 和开源硬件之间的交集

    导读 来认识一下Amber Matz,她是来自 Lullabot Education 旗下的Drupalize.Me的产品经理以及培训师.当她没有倒腾 Arduino.Raspberry Pi 以及电 ...

  9. 自定义错误信息并写入到Elmah

    在ap.net Web项目中一直使用Elmah进行日志记录, 但一直有一个问题困扰我很久,那就是我如何自己生成一个错误并记录到Elmah里去. 你知道有时你需要在项目中生成一个错误用于一些特殊的需求 ...

  10. STL - 移除(remove)和释放(erase)集合元素

    remove(移除): 这个操作并不是真正地删除元素,它会移除指定的元素,然后后面的元素依次前移,最后用别的元素来补充. erase(释放): 这个操作会指定释放区间的头和尾迭代器(iterator) ...