
函数调用函数参数传入寄存器保护现场过程省略或压栈调用函数代码函数中按预设的入栈顺序使用参数调用惯例基于函数调用过程中参数传递原理函数调用方与被调用方对于传递和使用参数需要有一致的理解。因此需要调用惯例。调用惯例函数参数的传递顺序和方式栈的维护方式函数调用时将所有函数参数压栈在调用完成后需将所有参数出栈。出栈的工作可由函数的调用方完成也可由函数本身被调用方完成。名字修饰的策略在原函数名基础上按设定规则加上修饰汇编代码中可查看C语言默认调用惯例cdecl// 选择调用惯例// 定义__attribute__((cdecl))voidfoo(inta,intb){printf(a%d, b%d\n,a,b);}// 声明__attribute__((cdecl))voidfoo(int,int);x86-64 有统一的调用约定System V AMD64 ABI, 不能自定义变长参数函数变长参数的标准库头文件stdarg.h实现不定参数的步骤定义函数函数的最后一个参数使用省略号…省略号前可以有固定参数。函数内创建va_list变量这是一个在stdarg.h中定义的类型用于访问参数列表。初始化参数列表使用va_start宏和最后一个固定参数来初始化va_list变量。访问参数使用va_arg宏和va_list变量来访问每个参数。结束参数列表访问使用va_end宏清理va_list变量。#includestdarg.h#includestdio.h// 变长参数函数示例intfunc_name(intarg1,...){va_list ap;va_start(ap,arg1);intarg2va_arg(ap,int);doublearg3va_arg(ap,double);char*arg4va_arg(ap,char*);printf(%d %lf %s\n,arg2,arg3,arg4);va_end(ap);returnarg1;}intmain(){func_name(3,1,1.5,abc);return0;}arg1是函数的第一个参数省略号…表示后续的参数数量是可变的。要使用这种机制需要包含stdarg.h头文件它提供了处理可变参数的宏和函数。可见可变参数的函数的参数分为两种类型固定参数只表意和不定参数固定参数在前不定参数在后。变长参数宏##为宏字符串连接// 1.gcc编译下的定义#definemprintf(arg...)fprintf(stdout,##arg)// 2.MSVC下的定义#definemprintf(...)fprintf(stdout,__VA_ARGS__)// 使用mprintf(%d %lf %s\n,1,1.5,abc);