C语言中的危险函数有,C语言中va(可变函数参数) 的另一种用法与危险事项

c语言中的可变参数va(va_arg) 大家应该比较熟悉了,主要是用来解决函数参数类型与个数不确定的问题,基本用法与详细请移步这里 /kf/201202/119885.html

通常的用法是把va_arg放在等号右边,提取其值来使用:

[cpp]

func( type para1, type para2, type para3, ... )

{

/****** step 1 ******/

va_list ap;

va_start( ap, para3 ); //一定要“...”之前的那个参数

/****** step 2 ******/

//此时ap指向第一个可变参数

//调用va_arg取得里面的值

type xx = va_arg( ap, type );

//type一定要相同,如:

//char *p = va_arg( ap, char *);

//int i = va_arg( ap, int );

//如果有多个参数继续调用va_arg

/****** step 3 ******/

va_end(ap); //for robust!

}

这里介绍va的另一种用法:把va_arg()当左值使用:

[cpp]

//函数定义:

passinto(id, ...)

{

va_list valist;

va_start(valist, id);

*(uint32_t*)va_arg(valist, uint32_t*) = 10;

va_end(valist);

}

//调用:

uint32_t value = 0;

passinto(id, &value);

printf("%d", value);

得到结果是value被赋值为10。

可以看到,这里va_arg被放到了等号左边,好像很奇怪的用法,实际上分析一下,同放在右边原理都是一样的。因为不论va的原理如何(见上面的链接),

c语言的函数归根到底还是值传递的,在第一种通常的用法中,va值被取出来后赋值给其它变量,在第二种用法中,&value被当作va传了进去,

它的值其实就是一个指向value的指针,所以 va_arg(valist, uint32_t*) 取出的是一个uint32_t的指针,*(uint32_t*)va_arg(valist, uint32_t*) =10 即把这个指针强制类型转换为(uint32_t*)并加*号间接引用,

这样实际得到了变量value,现在把它赋值为10,就等价于

[cpp]

value = 10;

这样就完成了我们的全部操作,实现了对任意类型和个数的参数进行赋值。

这个方式超级灵活,但是注意不要进行下面的危险操作:

[cpp]

uint16_t value = 0;   //这里有变化

passinto(id, &value);

后果可能很严重。为什么呢?因为参数类型不匹配,16位的参数被强迫当作32位来使用。我们的value同志此时只从那里申请到了16bit的空间,而

[cpp]

*(uint32_t*)va_arg(valist, uint32_t*) =10

把10塞到了从value开始的32位空间,那么value之后的那16bit是哪里呢?由谁在用?不得而知。

如果运气好,没有人在用,程序无事,如果数据在用,那么数据会变化,系统在用,系统也跑偏。

反正我用的时候它没和我客气,系统直接崩溃了。

摘自 herbert的知识库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值