博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C处理不定参数(va_start)
阅读量:6233 次
发布时间:2019-06-21

本文共 1332 字,大约阅读时间需要 4 分钟。

hot3.png

在#include<stdarg.h>头里包含了四个宏

#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址

#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址

#define va_end(ap) ( ap = (va_list)0 )

函数实现的原理:

首先:进程中的堆栈地址是从高到底分配的,那么执行一个函数的过程:

先把参数地址入栈,接着是函数返回值地址入栈,接着入栈函数的执行代码。这个过程中地址不断递减(一些黑客就在这个过程中加入自己的代码执行)

最后一个参数地址  (最高地址)

倒数第二个参数地址 (次之)

。。

第一个参数  (参数列表最低地址)

函数返回值

函数执行代码

例子:

void arg_test(int i, ...)

{

int j=0;

va_list arg_ptr;

va_start(arg_ptr, i);

printf("&i = %p\n", &i);//打印参数i在中的地址

printf("arg_ptr = %p\n", arg_ptr);//打印va_start之后arg_ptr地址

/*这时arg_ptr应该比参数i的地址高sizeof(int)个字节,即指向下一个参数的地址*/

j=*((int *)arg_ptr);

printf("%d %d\n", i, j);

j=va_arg(arg_ptr, int);

printf("arg_ptr = %p\n", arg_ptr);//打印va_arg后arg_ptr的地址

/*这时arg_ptr应该比参数i的地址高sizeof(int)个字节,即指向下一个参数的地址,如果已经是最后一个参数,arg_ptr会为NULL*/

va_end(arg_ptr);

printf("%d %d\n", i, j);

}

总结:

int int_size = _INTSIZEOF(int);得到int类型所占字节数

va_start(arg_ptr, i); 得到第一个可变参数地址

根据定义(va_list)&v得到起始参数的地址, 再加上_INTSIZEOF(v) ,就是其实参数下一个参数的地址,即第一个可变参数地址.

j=va_arg(arg_ptr, int); 得到第一个可变参数的值,并且arg_ptr指针上移一个_INTSIZEOF(int),即指向下一个可变参数的地址.

va_end(arg_ptr);置空arg_ptr,即arg_ptr=(void *)0;

总结:读取可变参数的过程其实就是在堆栈中,使用指针,遍历堆栈段中的参数列表,从低地址到高地址一个一个地把参数内容读出来的过程.

转载于:https://my.oschina.net/Jesuslovesyou/blog/193804

你可能感兴趣的文章
html5: Drag and Drop
查看>>
解决微信多域名授权微信网页授权订阅号借用授权无公众号代授权
查看>>
Python日志产生器
查看>>
Java——内部类(inner class)
查看>>
【NOI 2009】诗人小G
查看>>
(九)ASP.NET自定义用户控件(2)
查看>>
真机调试出现错误 No provisioning profiles found: No non–expired provisioning profiles were f...
查看>>
窗体的置顶显示
查看>>
第五次作业(团队作业)
查看>>
URL重定向之一.htaccess文件和AllowOverride指令
查看>>
Dedecms去掉网站底部powered by dedecms 的方法
查看>>
2017中国大学生程序设计竞赛-哈尔滨站 A - Palindrome
查看>>
数组求和函数
查看>>
Pos管理类库的第三方库
查看>>
在局域网中通过端口号扫描服务器IP
查看>>
在android 采用 android junit test 测试注意
查看>>
【转】网页禁止后退键BackSpace的JavaScript实现(兼容IE、Chrome、Firefox、Opera)
查看>>
登录界面点击登录后如何延迟提示成功的div的显示时间并跳转
查看>>
MySQL 数据库死锁
查看>>
关于try catch
查看>>