关于C语言的变长函数,首先使用 stdarg.h 头文件的定义实现:
#include <stdio.h>
#include <stdarg.h>
int sum(int num, ...)
{
int sum = 0;
va_list ap;
va_start(ap, num);
for (int i = 0; i < num; i++)
{
sum += va_arg(ap, int);
}
va_end(ap);
return sum;
}
int main(int argc, char* argv[])
{
printf("%d\r\n", sum(4, 1, 2, 3, 4));
return 0;
}
如上代码实现变长参数相加,第一个参数为参数个数-1。从代码内容可知,如果需要引用变长参数,首先需要定义一个va_list型变量,然后调用va_start并传入第一个参数,然后每获取一个参数就调用一次va_arg并传入数据类型,最后调用va_end。
但如果代码的需要,需要随机访问某参数或者从右往左访问元素,该如何实现呢?首先我们得使用内联汇编实现变长函数功能。
#include <stdio.h>
int sum(int num, ...)
{
int sum = 0;
int _ptr = 12;
for (int i = 0; i < num; i++)
{
__asm {
mov ecx, ebp;
add ecx, _ptr;
mov ebx, [ecx];
add sum, ebx;
add _ptr, 4;
}
}
return sum;
}
int main(int argc, char* argv[])
{
printf("%d\r\n", sum(4, 1, 2, 3, 4));
return 0;
}
首先,我们姑且将第一个参数用“参数0”表示。首先,在内联汇编中,ebp为栈底指针,ebp+4为当前函数返回的地址,那么ebp+8就是参数0的地址,依此类推,ebp+12就是参数1的地址。上面的内联汇编意思就是依次取出参数并加进sum里面。
由以上代码,大家应该就能推理出如何实现随机访问变长参数了。这里我还是给出内联汇编代码:
//访问参数i并存入变量a中
__asm {
mov ecx, i;
mul ecx, 4;
add ecx, ebp;
add ecx, 8;
mov eax, [ecx];
mov a, eax;
}