不知在座各位有没有想过,为什么printf,scanf的函数参数总是不定长呢?这是“惯例”?恐怕不是,我以前倒想过,解决方案是void*列表(笑),但完全无法用,遂弃。到后来深入了解C语言时,终于发现了stdargs.h和varargs.h(已弃用)这些宏库。凭借着{...}变参语法和自己对C语言的了解,简单地搓了一个变参宏Vaget。分析流程和代码实例见文末。
// Link Here: //
typedef char* va_lst;
#define va_mcl ...
#define va_start(val,mod) ((char*)(&val)+sizeof(mod))
#define va_get(va,mod) (*((mod*)va))
#define va_pas(va,mod) (va+=sizeof(mod),0)
// LnkEnd //
上面的Vaget实现包含了一组宏和一个typedef将char*包装,宏va_mcl作为函数参数需放在列表的末尾,宏va_start启用参数列表,va_get获得mod类型的参数,va_pas用来取得宏列表的下一项
以上便是对这组宏的简析了。
分析流程
首先让我们做一个小小的假定,所有参数的内存地址是连续的,也就是说,foo(int a,int b,int c),则内存分配如下(每一个【:】都代表一字节)
|::::|::::|::::| 12 Bytes
a b c
// 当sizeof(int)为(size_t)4时
那么,我们只需要知道a的内存地址,就能推断出b,c的内存地址,自然而然能取其值了。
// 当a的内存地址为0x70时
a: 0x70
b: 0x74 = a+sizeof(int)
c: 0x78 = a+sizeof(int)+sizeof(int) = b+s

最低0.47元/天 解锁文章
544






