可变参数表 C语言 多态,C语言可变长参数实现“多态”

一、问题来源

先看看困惑来来源:

03b8cab4bf3a2ac87d1bd184f610723a.png

这让我很疑惑,难道c也支持“多态”的特性么?貌似没见过呀~

二、解决方案

google帮忙,明白了一二,特此记录:

原来这种“多态”是通过c语言的可变长参数实现的(python也具有这种特性)

有关可变长参数的介绍见文章末尾的参考列表,说的很详细。

截取关键的内容:

1.可变长参数的宏定义:

(学习宏函数的典例呀)

// stdarg.h

#define va_start _crt_va_start

#define va_arg _crt_va_arg

#define va_end _crt_va_end

// vadefs.h

typedef char * va_list;

#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) )

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

2.可变长参数的宏介绍:

C语言可变参数通过三个宏(va_start、va_end、va_arg)和一个类型(va_list)实现,

void va_start ( va_list ap, paramN );

参数:

ap: 可变参数列表地址

paramN: 确定的参数

功能:初始化可变参数列表(把函数在 paramN 之后的参数地址放到 ap 中)。

void va_end ( va_list ap );

功能:关闭初始化列表(将 ap 置空)。

type va_arg ( va_list ap, type );

功能:返回下一个参数的值。

va_list :存储参数的类型信息。

好了,综合上面3个宏和一个类型可以猜出如何实现C语言可变长参数函数:用 va_start 获取参数列表(的地址)存储到 ap 中,用 va_arg 逐个获取值,最后用 va_arg 将 ap 置空。

按照说明,我实现了一个简单的测试代码,来测试可变长参数:

/*************************************************************************

* @File Name: test.c

* @Author: kehr

* @Mail: kehr163@163.com

* @Created Time: 2013年11月30日 星期六 19时06分32秒

* @Copyright: GPL 2.0 applies

* @Purpose: 测试可变长参数,实现c的“多态”

*************************************************************************/

#include

#include

void show(int first_param,int flag, ...);

int main()

{

show(1,2,3,4,5);

return 0;

}

void show(int first_param,int flag, ...)

{

//定义参数列表

va_list vl;

//初始化参数列表

va_start (vl, flag);

//获取参数值

printf ("%d ",first_param);

printf ("%d ",flag );

printf("%d ",va_arg(vl,int));

printf("%d ",va_arg(vl,int));

printf("%d ",va_arg(vl,int));

printf("\n");

//关闭参数列表

va_end(vl);

}

那么这个清楚了以后,用来实现c的“多态”就好办了。修改上面的代码,实现“多态”:

/*************************************************************************

* @File Name: test.c

* @Author: kehr

* @Mail: kehr163@163.com

* @Created Time: 2013年11月30日 星期六 19时06分32秒

* @Copyright: GPL 2.0 applies

* @Purpose: 测试可变长参数,实现c的“多态”

*************************************************************************/

#include

#include

#define _NAME 0

#define _NAME_AGE 1

void show(int first_param,int flag, ...);//对外暴露的接口

void showName(char* name);//内部的实现

void showNameAndAge(char* name, int age);//内部的实现

int main()

{

//如果不看show的具体实现,那么下面这两句代码不就是“多态”了么?

show(1,_NAME,"xiaogqiang");

show(2,_NAME_AGE,"xiaoqiang",23);

return 0;

}

void show(int first_param,int flag, ...)

{

//这里地一个参数没有做处理,完全可以直接输出,或进行其它处理

printf("%d\n",first_param);

//定义参数列表

va_list vl;

//需要处理的参数

char* name;

int age;

//初始化参数列表

va_start (vl, flag);

//获取参数值

//printf("flag=%d\n",flag);

//printf("name=%s\n",va_arg(vl,char*));

//printf("age=%d\n",va_arg(vl,int));

//单独使用下面这条语句无法得到结果,猜测是printf的内部原因。

//printf("name=%s\n age=%d\n",va_arg(vl,char*),va_arg(vl,int));

//根据标志选择要处理的函数

switch(flag)

{

case _NAME:

showName(va_arg(vl,char*));

break;

case _NAME_AGE:

name = va_arg(vl,char*);

age = va_arg(vl,int);

showNameAndAge(name,age);

break;

default:

printf("没有匹配的函数!\n");

}

//关闭参数列表

va_end(vl);

}

void showName(char* name)

{

printf("name=%s\n",name);

}

void showNameAndAge(char* name, int age)

{

printf("name=%s\nage=%d\n",name,age);

}

结果如下:

bb8ac1f80b91915e687698e52cb92530.png

三、IDE

(我用的是vim编辑的,可能界面有些人会不习惯。上张我的vim编辑图)

3b96fa91cd3583f16fd8385eb46201c4.png

感兴趣的朋友,我可以把我的vimrc共享,目前文件配置超过600行,分割了一下感觉好点了。

vim初用很难受,用久了就月来越离不开了。程序员编程利器,建议学一下。

四、总结

通过这个例子的测试,我知道C的强大也是毋庸置疑的。面向过程的语言也可以借用面向对象的思想,二者没有绝对的鸿沟。对于C来说,某个方面可能不擅长,但是并不但表做不了。还有许多好玩儿的特性,待我慢慢去挖出来。

这个例子中的思想在c的很多函数都有所体现,除了文章开头介绍的open函数外还有很多。说明了在C的标准实现里面这些特性占据着很重要的的地位。借用面向对象的思想解决问题,这也便是面向过程和面向对象的结合。

最近要写点对面向对象的思考。是时候总结一下了。

五、参考

http://www.cnblogs.com/chinazhangjie/archive/2012/08/18/2645475.html

http://club.topsage.com/thread-2263309-1-1.html有关

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值