純C/C++語言 函數參數數量可變的原理和應用

純C/C++語言 函數參數數量可變的原理和應用

純C/C++語言 函數參數數量可變的原理和應用


資料來源: https://mp.weixin.qq.com/s/rtKFhVMo_RyCIhPVmrLeig

線上編譯: https://www.tutorialspoint.com/compile_c_online.php


    C語言中沒有函數重載,解決不定數目函數參數問題變得比較麻煩;即使採用C++,如果參數個數不能確定,也很難採用函數重載.對這種情況,有些人採用指針參數來解決問題


原理:

VA_LIST 是在C語言中解決變參問題的一組宏,原型:
typedef char* va_list;
其實就是個char*類型變量


基本code:

#include <stdio.h>
#include <stdarg.h>
int AveInt(int, ...);
void main()
{
    printf("%d\t", AveInt(2, 2, 3));
    printf("%d\t", AveInt(4, 2, 4, 6, 8));
    return;
}

int AveInt(int v, ...)
{
    int ReturnValue = 0;
    int i = v;
    va_list ap;
    va_start(ap, v);
    while (i > 0)
    {
        ReturnValue += va_arg(ap, int);
        i--;
    }
    va_end(ap);
    return ReturnValue /= v;
}

高級應用(純粹收集沒執行過):

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
/*定义一个回调函数指针*/
typedef void (*libvlcFormattedLogCallback)(void* data, int level, const void* ctx, const char* message);
enum libvlc_log_level { 
    LIBVLC_DEBUG = 0,       //调试
    LIBVLC_NOTICE = 2,      //普通
    LIBVLC_WARNING = 3,     //警告
    LIBVLC_ERROR = 4 }      //错误
;
/*定义一个回调函数结构体*/
typedef struct CallbackData {
    void* managedData;
    libvlcFormattedLogCallback managedCallback;
    int minLogLevel;        //log 级别
} CallbackData;

/*构造回调函数结构体*/
void* makeCallbackData(libvlcFormattedLogCallback callback, void* data, int minLevel)
{
    CallbackData* result = (CallbackData *)malloc(sizeof(CallbackData));
    result->managedCallback = callback;
    result->managedData = data;
    result->minLogLevel = minLevel;
    return result;
}

/*回调函数*/
void formattedLogCallback(void* data, int level, const void* ctx, const char* message)
{
    printf("level:%d", level);
    if (level == LIBVLC_ERROR)
    {
        printf("LIBVLC_ERROR:%s", message);
        return;
    }
    if (level >= LIBVLC_WARNING) {
        printf("LIBVLC_WARNING:%s", message);
        return;
    }
    if (level >= LIBVLC_NOTICE)
    {
        printf("LIBVLC_ERROR:%s", message);
        return;
    }
    if (level >= LIBVLC_DEBUG) {
        printf("LIBVLC_WARNING:%s", message);
        return;
    }
    
    
}

/*和石化log信息并执行回调函数*/
void InteropCallback(void* data, int level, const void* ctx, const char* fmt, va_list args)
{
    CallbackData* callbackData = (CallbackData*)data;
    if (level >= callbackData->minLogLevel)
    {
        va_list argsCopy;
        int length = 0;

        va_copy(argsCopy, args);
        length = vsnprintf(NULL, 0, fmt, argsCopy);
        va_end(argsCopy);

        char* str = malloc(length + 1);
        if (str != NULL)
        {
            va_copy(argsCopy, args);
            vsprintf(str, fmt, argsCopy);
            va_end(argsCopy);
        }
        else
        {
            // Failed to allocate log message, drop it.
            return;
        }
        callbackData->managedCallback(callbackData->managedData, level, ctx, str);
        free(str);
    }
}
void sendLog(void* data, int level, const void* ctx, const char* fmt, ...)
{
    va_list va;
    va_start(va, fmt);
    InteropCallback(data, level, ctx, fmt, va);
    va_end(va);
}
int main(int argc, char** argv)
{
    /*注册一个回调函数结构体,level等级为LIBVLC_WARNING 只要发送的log等级大于等于LIBVLC_WARNING次啊会触发回调函数*/
    void* callbackData = makeCallbackData(formattedLogCallback, "context", LIBVLC_WARNING);
    /*发送四个等级的消息*/
    sendLog(callbackData, LIBVLC_DEBUG, NULL, "This should not be displayed : %s\n","debug");
    sendLog(callbackData, LIBVLC_NOTICE, NULL, "This should not be displayed : %s\n", "notick");
    sendLog(callbackData, LIBVLC_WARNING, NULL, "This message level is : %s\n", "warning");
    sendLog(callbackData, LIBVLC_ERROR, NULL, "Hello, %s ! You should see %ld message here : %s\n", "World", 1, "warning message");

    free(callbackData);
    return 0;
}

心得:

    我只看得懂基本的範例,就覺得很好用了 哈哈

One thought on “純C/C++語言 函數參數數量可變的原理和應用

  1. 純C/C++語言 函數參數數量可變的原理和應用
    傳遞 參數 數量 動態 不固定 任意個數 任意長度
    前提條件:變數型態一致

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *