C/C++函数可变参量传递

函数的可变参量传递是什么呢?就是你设定的函数在传入参数的时候你不知道传入参数的数量和顺序。为了解决这个问题一般用两种办法,第一个就是函数重载,第二个就是使用可变参量。第一个方法也是使用最多的办法,但是第一个方法有一个问题就是只有在解决传入参量变化不是很大的时候才行,要是传入的参量从几个到几百个不等,那么要使用函数重载是不现实的。

函数可变参量的传递其实学过C语言的都用过,最常见的就是printf函数,这个函数传入的参量有很多,从几个到几百个不等,那么它是怎么实现的呢?

其实解决办法就是使用指针来解决,假设我定义了一个指针,它能够指向我不确定传入参量的起始位置,然后一直指向下一个传入参量,直到参量遍历完毕。但是C中的指针并不是每个人都能很轻松应用的。所以为了更方便使用定义了一系列的宏,开发者可以像函数一样直接使用这些宏来完成,具体的一些宏如下所示:

  1. #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1)
  2. #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
  3. #define va_arg(ap,v) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
  4. #define va_end(ap) ( ap = (va_list)0 )

这个指针包含在头文件中,名为va_list定义的宏。上面给出的宏主要是操作va_list指针的,现在解释一下以上的宏操作。

第一个操作是假设有一个变量为 n n n,对变量 n n n的内存大小向上取int大小的整数倍。首先看公式 s i z e o f ( i n t ) − 1 sizeof(int)-1 sizeof(int)1,这个公式得到的值在二进制中是不是一定是一个低位全 1 1 1,例如假设在系统中int为 4 4 4个字节,那么 s i z e o f ( i n t ) sizeof(int) sizeof(int)值为 4 4 4,二进制中为 100 100 100,减一之后为 011 011 011,那么 s i z e o f ( n ) + s i z e o f ( i n t ) − 1 sizeof(n)+sizeof(int)-1 sizeof(n)+sizeof(int)1也就是说如果 n n n的大小不是int的整数倍那么加上一个 s i z e o f ( i n t ) − 1 sizeof(int)-1 sizeof(int)1一定会在 s i z e o f ( i n t ) sizeof(int) sizeof(int)的最高位对应的位置加 1 1 1。而~(sizeof(int)-1)则是取反 ( s i z e o f ( i n t ) − 1 ) (sizeof(int)-1) (sizeof(int)1)产生的低位全 0 0 0,例如对 011 011 011取反的到 100 100 100,这个数和上面得到的结果且起来产生的低位全 0 0 0,这样就得到了将 n n n的内存大小向上变成int的整数倍。

第二个操作是,假设有一个va_list指针名为ap,那么操作为初始化ap指向的地址。ap值为名为v参数变量的下一个变量地址。这里要求v为可变参量前的最后一个参量,也就是说假设函数定义为void fun(int cnt , int cnt2, ...),那么只能将ap指向cnt2的后一位。

第三个操作就是返回ap指向的当前地址的值并且将ap值改为下一位参量的地址。

最后一个操作就是将ap指针清空,结束。

具体使用代码如下所示:

#include 
#include 
using namespace std;

void fun(int cnt, ...) {
     
    va_list all_name;

    va_start(all_name, cnt);
    for(int i=0;i<3;i++) {
     
        char *_name = va_arg(all_name, char*);
        cout <<_name<<" ";
    }
    va_end(all_name);
}

int main() {
     
    fun(2, "hello", "world");
    return 0;
}

你可能感兴趣的:(编程基础,c++,可变参量传递)