C++.可变参数_ZC测试

ZC:环境: Win7 x64(旗舰版),Microsoft Visual Studio 2010(版本 10.0.30319.1 RTMRel, Microsoft .NET Framework(版本 4.0.30319 RTMRel))

1、代码:

#include <stdio.h>
#include <stdarg.h>
#include <windows.h>

int sum(int count, ...);//原型中使用省略号

// 函数的参数为:DWORD _dw, HWND _h, char* _pc
void TextZ(int _n, ...)// ZC: 貌似无法动态获得参数的个数,∴只能在参数中带上参数的个数(需要的话),我一般放在可变参数前面的位置。
{
    va_list ap;//声明一个va_list变量
    va_start(ap, _n);//初始化,第二个参数为最后一个确定的形参// ZC: 需要 参数个数 作为函数va_start(...)的参数

    // ZC: 貌似参数只能依次取,不能随机取?
    DWORD dw = va_arg(ap, DWORD);//读取可变参数,的二个参数为可变参数的类型
    HWND h = va_arg(ap, HWND);
    char* pc = va_arg(ap, char*);

    va_end(ap);//清理工作

    // ***

    printf("DWORD : %d, HWND : %d, char* : %s
", dw, h, pc);
}

// 下面的函数 和 上面的函数 几乎一模一样,只是这里是使用 指针来取得可变参数,这里是尝试其可行性
void TextZ01(int _n, ...)// ZC: 貌似无法动态获得参数的个数,∴只能在参数中带上参数的个数(需要的话),我一般放在可变参数前面的位置。
{
    va_list ap;//声明一个va_list变量
    va_start(ap, _n);//初始化,第二个参数为最后一个确定的形参// ZC: 需要 参数个数 作为函数va_start(...)的参数

    // ZC: 貌似参数只能依次取,不能随机取?
    DWORD* pdw = &va_arg(ap, DWORD);//读取可变参数,的二个参数为可变参数的类型
    HWND* ph = &va_arg(ap, HWND);
    char** ppc = &va_arg(ap, char*);

    va_end(ap);//清理工作

    // ***

    printf("DWORD : %d, HWND : %d, char* : %s
", *pdw, *ph, *ppc);
}

void main()
{
    //int i = sum(3, 4,5,6);
    //printf("sum : %d
", i);

    TextZ(3, 567, 30303030, "TextZ");
    TextZ01(3, 567, 30303030, "TextZ");
    system("pause");
}

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

int sum(int count, ...)//count 表示可变参数个数
{
    va_list ap;//声明一个va_list变量
    va_start(ap, count);//初始化,第二个参数为最后一个确定的形参

    int sum = 0;
    for(int i = 0; i < count; i++)
        sum += va_arg(ap, int);//读取可变参数,的二个参数为可变参数的类型

    va_end(ap);//清理工作
    return sum;
}

2、控制台输出:

  

3、

4、自己的包装函数(1)

  ZC:主要是在 函数内部去使用 sprintf_s(...) 来组合字符串,省的写在外面(写在外面 代码太多太乱 看不清晰)

  ZC:下面,函数传入的可变参数 都是 DWORD类型的,如果需要 不同的类型的话,可以在可变参数中加入指定参数类型的参数,见下面的"5"

void ShowMsg_Thread_DLL_VA_DWORD(char* _pc, int _n, ...)
{
    if (g_fnShowMsg_Thread == NULL)
        return;
    if (_n > 5)
    {
        ::MessageBoxA(0, "Parameter count not enough .", "ShowMsg_Thread_DLL_VA_DWORD", 0);
        return;
    }

    DWORD dws[16] = {0};
    char buf[512] = {0};

    va_list ap;
    va_start(ap, _n);

    if (_n == 0)
        g_fnShowMsg_Thread(_pc);
    else if (_n == 1)
    {
        dws[0] = va_arg(ap, DWORD);
        sprintf_s(buf, sizeof(buf), _pc, dws[0]);
    }
    else if (_n == 2)
    {
        for (int i=0; i<_n; i++)
            dws[0] = va_arg(ap, DWORD);
        sprintf_s(buf, sizeof(buf), _pc, dws[0], dws[1]);
    }
    else if (_n == 3)
    {
        for (int i=0; i<_n; i++)
            dws[0] = va_arg(ap, DWORD);
        sprintf_s(buf, sizeof(buf), _pc, dws[0], dws[1], dws[2]);
    }
    else if (_n == 4)
    {
        for (int i=0; i<_n; i++)
            dws[0] = va_arg(ap, DWORD);
        sprintf_s(buf, sizeof(buf), _pc, dws[0], dws[1], dws[2], dws[3]);
    }
    else if (_n == 5)
    {
        for (int i=0; i<_n; i++)
            dws[0] = va_arg(ap, DWORD);
        sprintf_s(buf, sizeof(buf), _pc, dws[0], dws[1], dws[2], dws[3], dws[4]);
    }

    va_end(ap);
    g_fnShowMsg_Thread(buf);
}

5、自己的包装函数(2)

  ZC:函数传入的可变参数,如果需要是 不同的类型的话,可以在可变参数中加入指定参数类型的参数,例如 我在 D?SvgExe的D?RemoteCall代码中的使用方式

6、

7、(20191112)Qt598x64(vs2017) 编译的"Widgets Application"中 printf(...)和fprintf(...)调用后,不会立即在控制台输出信息,需要调用"fflush(stdout);"后 信息才会显示出来,于是就想 封装一个信息打印的函数 在函数中直接调用 fflush(...),这就需要 封装成可变参数的函数,于是查了资料,封装成这样:

#include <stdarg.h>

void MsgPrint(const char *format, ...)
{
    va_list ap;
    int n;

    va_start(ap, format);
    n = vprintf(format, ap);
    va_end(ap);
    //return n;

    // ZC: 上面是 printf(...)的实现
    fflush(stdout);// Qt598不执行这一句的话 print(...)和fprintf(stdout, ...)输出的信息 不会立即显示在"应用程序输出"中
}

 (1)va_list 、va_start、 va_arg、 va_end 使用说明 - 土戈 - CSDN博客.html(https://blog.csdn.net/f110300641/article/details/83822290

// 附:可变参数应用实例

//  1.printf实现

#include <stdarg.h>
 
int printf(char *format, ...)
{
    va_list ap;
    int n;
     
    va_start(ap, format);
    n = vprintf(format, ap);
    va_end(ap);
    return n;    
}


//  2.定制错误打印函数error

#include  <stdio.h>
#include  <stdarg.h>
 
void error(char *format, ...)
{
    va_list ap;
    va_start(ap, format);
    fprintf(stderr, "Error: ");
    vfprintf(stderr, format, ap);
    va_end(ap);
    fprintf(stderr, "
");
    return;    
}

8、

9、

原文地址:https://www.cnblogs.com/cppskill/p/8716242.html