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

问题描述

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
", iNum);
}

解决方案

函数内部对可变参数都用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()收尾就可以解析可变参数了。

解决方案二:

C函数动态参数问题
C++中数组的引用作为函数参数
c++中函数使用类对象作参数的问题

解决方案三:

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
", iNum);
}

时间: 2024-11-08 19:01:21

va_list-c++动态参数函数中使用引用问题的相关文章

《C++面向对象高效编程(第2版)》——3.16 从函数中返回引用

3.16 从函数中返回引用 C++面向对象高效编程(第2版)要尽可能避免从函数返回引用.原因如下: (1)能从函数安全返回对某对象的引用(假定为foo)时,该函数不能创建对象foo.否则,谁对新创建对象的存储区负责?因为它不能是局部对象,这意味着在调用foo()之前, 左值(L-value)语义的含义 左值可用在赋值操作符的左则(LHS).例如,a = b表示a将被修改,而且它是一个左值.许多C++(和C)的操作符都要求正确地操作左值.所有其他操作符与赋值号结合的操作符,例如,+=./=等都是左

C++语言基础 例程 函数中的引用

贺老师的教学链接  本课讲解 引用作为形参 #include<iostream> using namespace std; class Sample { int x; public: Sample(int a): x(a) {cout<<"A";} Sample(Sample &a): x(a.x) {cout<<"B";} int getX(){return x;} }; void disp(Sample &s)

C#中关于引用传递的问题

问题描述 我想实现:有一引用变量,如ObjectA:然后有一个数据块,比如用结构体记录一些信息,其中包括A的引用信息.然后一个程序段通过操作这个数据块,能够给A付值.这在C++里应该比较容易实现,比如用指向指针的指针等,但在C#里好像没有实现的方法.C++例子大概如下:classA{}A*a;structX{A**P;}程序段intmain(){AnewA;XnewX;X.P=&a;//其他操作...........................*(X.P)=&newA;//这样就把ne

c++问题-C++的类中怎么在一个函数中引用上一层的函数

问题描述 C++的类中怎么在一个函数中引用上一层的函数 在同一个类中怎么引用先定义的函数来定义函数?比如在一个时期类的定义中,一个日期加1的函数中怎么调用先定义的一个求是否闰年的函数. 解决方案 C++定义隐式转换函数将类转换为内部的一个成员变量c++函数默认参数是一个好的设计吗? 解决方案二: 直接在函数内调用就可以了.不知道你说的上一层是什么意思.是基类的函数还是集合类所属的对象的函数,前者直接调用,或者用 基类类名::函数名后者用构造函数传对象指针 解决方案三: 同一个类中的函数都是通过t

动态网页PHP中引用&amp;的使用注意事项

之前一个朋友的帖子提到过这方面的疑问,这里简单整理一下,希望能让更多新学php的朋友得到帮助. php的引用(就是在变量或者函数.对象等前面加上&符号)是个高级话题,新手多注意,正确的理解php的引用很重要,对性能有较大影响,而且理解错误可能导致程序错误! 很多人误解php中的引用跟C当中的指针一样,事实上并非如此,而且很大差别.C语言中的指针除了在数组传递过程中不用显式申明外,其他都需要使用*进行定义,而php中对于地址的指向(类似指针)功能不是由用户自己来实现的,是由Zend核心实现的,ph

c++中拷贝构造函数的参数类型必须是引用

如果拷贝构造函数中的参数不是一个引用,即形如CClass(const CClass c_class),那么就相当于采用了传值的方式(pass-by-value),而传值的方式会调用该类的拷贝构造函数,从而造成无穷递归地调用拷贝构 造函数.因此拷贝构造函数的参数必须是一个引用   在C++中, 构造函数,拷贝构造函数,析构函数和赋值函数(赋值运算符重载)是最基本不过的需要掌握的知识. 但是如果我问你"拷贝构造函数的参数为什么必须使用引用类型?"这个问题, 你会怎么回答? 或许你会回答为了

C语言中的可变参数函数的浅析(以Arm 程序中的printf()函数实现为例) .

我们在C语言编程中会遇到一些参数个数可变的函数,一般人对它的实现不理解.例如Printf():   Printf()函数是C语言中非常常用的一个典型的变参数函数,它 的原型为: int printf( const char* format, ...); 它除了一个参数format固定外,后面的参数的个数和类型是不确定的,如下列三种调用方法: 1.    printf("%d\n", i); 2.    printf("%s\n", "Hello World

向函数中传递指针和传递指针的引用的区别

如果是传递指针,那么会先复制该指针,在函数内部使用的是复制后的指针,这个指针与原来的指针指向相同的地址,如果在函数内部将复制后的指针指向了另外的新的对象,那么不会影响原有的指针:但 是对于传递指针应用,如果将传递进来的指针指向了新的对象,那么原始的指针也就指向了新的对象,这样就会造成内存泄漏,因为原来指针指向的地方已经不能再 引用了,即使没有将传递进来的指针指向新的对象,而是在函数结束的时候释放了指针,那么在函数外部就不能再使用原有的指针了,因为原来的内存已经被释放了   看个例子: #incl

c++-C#调用C++动态库DLL中的函数

问题描述 C#调用C++动态库DLL中的函数 C#调用C++动态库DLL中的函数,此函数参数中有bool(小写)类型的参数.c#该如何进行转换 解决方案 C#调用C++动态库dllC#调用C++动态库(dll)C#动态调用C++编写的DLL函数 解决方案二: bool类型的true 或false一般对应1和0.有的语言没有bool类型的.传递参数时可用整型替代. 解决方案三: public static extern int RD_CloseCom(bool IsOpen); 解决方案四: 在C