怎样获得可变参数函数中的参数的个数?(va_list)

wplian 2003-04-08 11:16:46
内容同标题
...全文
1702 7 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
突击召唤师 2003-04-08
  • 打赏
  • 举报
回复
http://bbs.gxnu.edu.cn/cgi-bin/bbscon?board=Programming&file=M.965445434.A&num=177&title=149
http://bbs.gxnu.edu.cn/cgi-bin/bbscon?board=Programming&file=M.1002846622.A&num=343&title=288
看看吧,介绍得很详细的。
wplian 2003-04-08
  • 打赏
  • 举报
回复
我看过这四个宏定义了,va_list va_start va_args va_end
是根据给出的参数类型逐个的计算下一个参数所在的地址
本身并没有保存参数列表的内存大小,更何况调进的参数的类型各不相同
所以得到参数的个数似乎不太可能,当然传递参数个数及传递特定的结束符除外
楼上的老兄写的程序我虽然看的不大明白
不过总感觉与其本身的宏定义的意思差不多,我还是用上面两个比较方便的方法吧
多谢各位了,结帖
zhouzhaohan 2003-04-08
  • 打赏
  • 举报
回复
之所以要这么做实在是因为只有函数的调用者才有足够的信息知道到底有多少参数,而被调用的人却对此一无所知。
zhouzhaohan 2003-04-08
  • 打赏
  • 举报
回复
你也可以通过在参数中传递参数的个数,或者使用类似printf之类的格式字符串实现。
你用的是什么CPU,是不是intel?
如果是的话就好一点,我想到一种做法,但是可能不通用。至于有多么不通用,我也很难保证。
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>


int test(int a,...)
{
int count;
int ra;
int instruction;
va_list marker;
va_start(marker,a);//也可以直接取地址

ra=(*(int *)((int)marker-8));//根据第一个参数的地址,在栈上取得函数返回地址
printf("Return address:%x ",ra);
instruction=(*(int *)(*(int *)((int)marker-8)));//取得返回地址的指令
printf("Instruction %x ",instruction);
count=((instruction&0xff0000)>>16)/4;//从指令中提取需要的信息,每个入口参数占4个字节,如果都是int的话。
printf("Count of argument %d ",count);
printf("\n");


}
void main()
{
test(1,2,3,4,5);
test(1,2,3,4);
test(1,2,3);
test(1,2);
test(1);
}
以上的做法基于了这样几种假定,但是我相对于同一个编译器而言,这些假定应该是一致的,否则这种做法也没有意义。
在调用函数时,caller将把参数压栈,在调用结束后,caller马上恢复栈,恢复是通过在esp寄存器上加上一定的数值,而这个数值就等于所有入口参数占的空间。同时恢复栈用的是一个固定的语句,addl num,%esp,因此就可以从这个语句中提取出我们需要的信息。而callee被调用后同样会压栈,而且一些固定信息会有固定的位置。函数的返回地址就属于这种情况。我们可以很容易在栈上栈到它,而这个地址存放的语句正是我们所需要的。
在我的机器上调用test(1,2,3,4,5)生成的汇编是:
pushl $0x05
pushl $0x04
pushl $0x03
pushl $0x02
pushl $0x01
call xxxxx
addl $0x14,%esp
上面的规律是可以利用的,来达到你的目的。
但是我想这可能和calling convention 和optimization也有一定关系。

zhouzhaohan 2003-04-08
  • 打赏
  • 举报
回复
mark
wplian 2003-04-08
  • 打赏
  • 举报
回复
其中一篇有一段是这样说的:
  调用者在实际调用参数个数可变的函数时,要通过一定的方法指明实际参数的个数,例如把最后一个参数置为空字符串(系统调用execl()就是这样的)、-1或其他的方式。

对于“其他的方式”是什么意思呢?是仅仅修改最后一个参数的不同样式,还是有其他的解决方法?我不懂,望各位大侠能给我解释。
wplian 2003-04-08
  • 打赏
  • 举报
回复
TO 楼上老兄: 我非常感谢你提供的资料,但同时我也很遗憾,那里并没有我想要的东西。上面给的示例程序与MSDN上的大相径庭,在参数表后都要加上一个 0、-1 或 '\0'等作为结束标志,而我就是想不要这些东西同时又能判断已经读到参数列表的末尾,希望大家能给我解决的方法。

24,857

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧