純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++語言 函數參數數量可變的原理和應用”
純C/C++語言 函數參數數量可變的原理和應用
傳遞 參數 數量 動態 不固定 任意個數 任意長度
前提條件:變數型態一致