2 lengguangyao lengguangyao 于 2016.04.08 21:42 提问

c++动态参数函数中使用引用问题

void fun(char* ftm, ...)
{
int temp = 10;
va_list va;
char* s1 = va_start(va,ftm);
// 怎样为引用赋值?
char outNum[_INTSIZEOF(int)];
sprintf_s(outNum, "%d", 10);
memcpy((char*)va, outNum, _INTSIZEOF(int));
//*((int *)((va += _INTSIZEOF(int)) - _INTSIZEOF(int))) = temp;
va_end(va);
}

void main()
{
int iNum = 0;
fun("", &iNum);
// 希望打印出10
printf("%d\n", iNum);
}

3个回答

qq423399099
qq423399099   Ds   Rxr 2016.04.08 21:49

函数内部对可变参数都用va_list及与它相关的三个宏来处理,这是实现变参参数的关键之处。

在中可以找到va_list的定义:

typedef char * va_list;

再介绍与它关系密切的三个宏要介绍下:va_start(),va_end()和va_arg()。

同样在中可以找到这三个宏的定义:

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )

#define va_end(ap) ( ap = (va_list)0 )

#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

其中用到的_INTSIZEOF宏定义如下:

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

来分析这四个宏:

va_end(ap)这个最简单,就是将指针置成NULL。

va_start(ap,v)中ap = (va_list)&v + _INTSIZEOF(v)先是取v的地址,再加上_INTSIZEOF(v)。_INTSIZEOF(v)就有点小复杂了。( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )全是位操作,看起来有点麻烦,其实不然,非常简单的,就是取整到sizeof(int)。比如sizeof(int)为4,1,2,3,4就取4,5,6,7,8就取8。对x向n取整用C语言的算术表达就是((x+n-1)/n)*n,当n为2的幂时可以将最后二步运算换成位操作——将最低 n - 1个二进制位清 0就可以了。

va_arg(ap,t)就是从ap中取出类型为t的数据,并将指针相应后移。如va_arg(ap, int)就表示取出一个int数据并将指针向移四个字节。

因此在函数中先用va_start()得到变参的起始地址,再用va_arg()一个一个取值,最后再用va_end()收尾就可以解析可变参数了。

lengguangyao
lengguangyao 答非所问,复制的吧
一年多之前 回复
CSDNXIAON
CSDNXIAON   2016.04.08 21:52

C函数动态参数问题
C++中数组的引用作为函数参数
c++中函数使用类对象作参数的问题
----------------------同志你好,我是CSDN问答机器人小N,奉组织之命为你提供参考答案,编程尚未成功,同志仍需努力!

lengguangyao
lengguangyao   2016.04.09 09:26

void fun(char* ftm, ...)
{
int temp = 10;
va_list va;
va_start(va,ftm);

///////////////////////////////
int *p = va_arg(va,int*);
*p=temp;
////////////////////////////
va_end(va);

}
void main()
{
int iNum = 0;
fun("", &iNum);
// 成功打印出10
printf("%d\n", iNum);
}

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!