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