十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
在C/C++中,对函数参数的扫描是从后向前的。C/C++的函数参数是通过压入堆栈的方式来给函数传参数的(堆栈是一种先进后出的数据结构),最先压入的参数最后出来,在计算机的内存中,数据有2块,一块是堆,一块是栈(函数参数及局部变量在这里),而栈是从内存的高地址向低地址生长的,控制生长的就是堆栈指针了,最先压入的参数是在最上面,就是说在所有参数的最后面,最后压入的参数在最下面,结构上看起来是第一个,所以最后压入的参数总是能够被函数找到,因为它就在堆栈指针的上方。printf的第一个被找到的参数就是那个字符指针,就是被双引号括起来的那一部分,函数通过判断字符串里控制参数的个数来判断参数个数及数据类型,通过这些就可算出数据需要的堆栈指针的偏移量了,下面给出printf("%d,%d",a,b);(其中a、b都是int型的)的汇编代码.
创新互联公司凭借在网站建设、网站推广领域领先的技术能力和多年的行业经验,为客户提供超值的营销型网站建设服务,我们始终认为:好的营销型网站就是好的业务员。我们已成功为企业单位、个人等客户提供了成都网站建设、做网站服务,以良好的商业信誉,完善的服务及深厚的技术力量处于同行领先地位。
.section
.data
string out = "%d,%d"
push b //最后的先压入栈中
push a //最先的后压入栈中
push $out//参数控制的那个字符串常量是最后被压入的
call printf
你会看到,参数是最后的先压入栈中,最先的后压入栈中,参数控制的那个字符串常量是最后被压入的,所以这个常量总是能被找到的。
通常情况下函数可变参数表的长度是已知的,通过num参数传入,这种函数比较容易实现。
C语言中可变参函数实现,主要通过VA_LIST宏及相关操作的几个宏。
一、涉及宏及说明:
所有相关宏均定义在stdarg.h中。
1、va_list: 可变参数列表指针。
2、va_start:获取可变参数列表的第一个参数的地址。
3、va_arg:获取可变参数的当前参数,返回指定类型并将指针指向下一参数。
4、va_end:清空va_list可变参数列表。
可变参函数的实现,就是这四个宏的使用。
二、代码举例:
在实际应用中,经常有获取若干个数最大值的情况,当数量比较大的时候,一般通过数组实现,但个数不多时,一般写一个max函数。 常规写法都是用到几个数的max,就写几个参数, 对此可以实现一个可变参数函数,第一个参数指定共计有多少数据,后续各个参数为要比较的值。
#include stdio.h
#include stdarg.h
int max(int n, ...)//可变参数函数。
{
int r,i;
va_list ap;//定义可变参数。
if(n == 0) return -1;//异常参数。
va_start(ap, n);//得到起始点。
for(i = 0; i n; i ++)
{
int v=va_arg(ap,int) ;//获取下一个参数值。
if(i == 0) r=v;
else if(rv) r=v;
}
va_end(ap);//结束可变参数。
return r;//返回结果。
}
可以用如下主函数测试:
int main()
{
printf("%d\n",max(1, 1));
printf("%d\n",max(2, 2,1));
printf("%d\n",max(3, 5,9, 4));
printf("%d\n",max(4, 8 , 3,1,9));
return 0;
}
分别测试了1,2,3,4个数值,求取最大值的情况。
测试结果:
1
2
9
9
我是计算机专业的,当初学c语言的时候也是好为难,也有一些心得体会
语言这种东西会随着接触的多就自然全都通了,需要时间,慢慢来,看到你问的这些问题跟我当初好像,感觉你学的支离破散,我建议你要系统的学c语言,
我有一个c语言的教程,txt的,我可以发给你,看看很有帮助,你问这些问题,即使通了也是不透彻
函数中包含了程序的可执行代码。每个C程序的入口和出口都位于函数main()之中。main()函数可以调用其他函数,这些函数执行完毕后程序的控制又返回到main()函数中,main()函数不能被别的函数所调用。通常我们把这些被调用的函数称为下层(lower-level)函数。函数调用发生时,立即执行被调用的函数,而调用者则进入等待状态,直到被调用函数执行完毕。函数可以有参数和返回值。
程序员一般把函数当作“黑箱”处理,并不关心它内部的实现细节。当然程序员也可以自己开发函数库。
说明一点,函数这一节很重要,可以说一个程序的优劣集中体现在函数上。如果函数使用的恰当,可以让程序看起来有条理,容易看懂。如果函数使用的乱七八糟,或者是没有使用函数,程序就会显得很乱,不仅让别人无法查看,就连自己也容易晕头转向。可以这样说,如果超过100行的程序中没有使用函数,那么这个程序一定很罗嗦(有些绝对,但也是事实)。
一、函数的定义
一个函数包括函数头和语句体两部分。
函数头由下列三不分组成:
函数返回值类型
函数名
参数表
一个完整的函数应该是这样的:
函数返回值类型 函数名(参数表)
{
语句体;
}
函数返回值类型可以是前面说到的某个数据类型、或者是某个数据类型的指针、指向结构的指针、指向数组的指针。指针概念到以后再介绍。
函数名在程序中必须是唯一的,它也遵循标识符命名规则。
参数表可以没有也可以有多个,在函数调用的时候,实际参数将被拷贝到这些变量中。语句体包括局部变量的声明和可执行代码。
我们在前面其实已经接触过函数了,如abs(),sqrt(),我们并不知道它的内部是什么,我们只要会使用它即可。
这一节主要讲解无参数无返回值的函数调用。