C语言的可变参数一点研究

可变参数对我多少有点诱惑,当初一开始学习C的时候,就被它迷惑了,我自己写的函数都是定参的,当时以我的功力,断是费上三天三夜功夫也搞不定可变参数。

在汇编的课开完之后,其实对c的一些技巧已经不稀奇了,C毕竟是C,而不像C++有太多的语法规定和编译器规定。

昨天头热,想再来看看这个变参,也许可以偶尔在工作上用一下。

参数是靠堆栈来保存的,其实看看堆栈就知道怎么来获取的了,那获取变参应该就简单了:1.在堆栈中获取数据2.将这些数据转换成参数的值。

加之C中已经有人做了这么几个宏:

C语言的可变参数一点研究C语言的可变参数一点研究代码

#define va_start _crt_va_start#define va_arg _crt_va_arg#define va_end _crt_va_end/* A guess at the proper definitions for other platforms */#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )#define _crt_va_end(ap)      ( ap = (va_list)0 )#define _ADDRESSOF(v)   ( &(v) )

对于这些宏,对于不同的平台定义是不一样的,但作用都是一样一样的。

我写了几行代码看了下堆栈

C语言的可变参数一点研究C语言的可变参数一点研究代码

#include "stdafx.h"#include <stdarg.h>void f(int n,...){     va_list arglist;     va_start(arglist,n);     int nArg = va_arg(arglist,int);     va_end(arglist);}int _tmain(int argc, _TCHAR* argv[]){    f(1,1,0x2);}

断点到f函数被调用那行,转到汇编下,可看到参数的入栈顺序,当然这里的调用约定是__cdecl,慢慢压栈,观察栈的变化,然后在跟踪进f看参数怎么出栈的。

其实一般可变参数不需要栈的,但是如果一个函数连一个定参都没有的话,那就不行的了va_的几个宏只能是根据最后一个定参的地址确定其他的地址的,如果没有一个定参,那么这几个宏,将无用武之地了,这个时候,可以直接在f中获取寄存器的esp即可,当然这样的函数也可能没有多大意义,而且可以被随意加个参数替代。

原文链接: https://www.cnblogs.com/20090802/archive/2010/12/30/1921333.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/19461

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月7日 下午8:33
下一篇 2023年2月7日 下午8:33

相关推荐