国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

C語言可變參數的原理和應用

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

 [[373935]]

本文轉載自微信公眾號「編程學習基地  」,作者deroy  。轉載本文請聯系編程學習基地  公眾號。 

概述

C語言中沒有函數重載,解決不定數目函數參數問題變得比較麻煩;

即使采用C++,如果參數個數不能確定,也很難采用函數重載.對這種情況,有些人采用指針參數來解決問題

var_list可變參數介紹

VA_LIST 是在C語言中解決變參問題的一組宏,原型:

  1. typedef char* va_list; 

其實就是個char*類型變量

除了var_list ,我們還需要幾個宏來實現可變參數

「va_start、va_arg、va_end」

  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,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )//下一個參數地址 
  4. #define va_end(ap)    ( ap = (va_list)0 )                  // 將指針置為無效 

簡單使用可變參數

  1. #include <stdio.h> 
  2. #include <stdarg.h> 
  3. int AveInt(int, ...); 
  4. void main() 
  5.     printf("%d\t", AveInt(2, 2, 3)); 
  6.     printf("%d\t", AveInt(4, 2, 4, 6, 8)); 
  7.     return
  8.  
  9. int AveInt(int v, ...) 
  10.     int ReturnValue = 0; 
  11.     int i = v; 
  12.     va_list ap; 
  13.     va_start(ap, v); 
  14.     while (i > 0) 
  15.     { 
  16.         ReturnValue += va_arg(ap, int); 
  17.         i--; 
  18.     } 
  19.     va_end(ap); 
  20.     return ReturnValue /= v; 

啊這..

可變參數原理

在進程中,堆棧地址是從高到低分配的.當執行一個函數的時候,將參數列表入棧,壓入堆棧的高地址部分,然后入棧函數的返回地址,接著入棧函數的執行代碼,這個入棧過程,堆棧地址不斷遞減,

「黑客就是在堆棧中修改函數返回地址,執行自己的代碼來達到執行自己插入的代碼段的目的」.

函數在堆棧中的分布情況是:地址從高到低,依次是:函數參數列表,函數返回地址,函數執行代碼段.

說這么多直接上代碼演示吧..

  1. #include <stdio.h> 
  2. #include <stdarg.h> 
  3. int AveInt(int, ...); 
  4. void main() 
  5.     printf("AveInt(2, 2, 4): %d\n", AveInt(2, 2, 4)); 
  6.     return
  7.  
  8. int AveInt(int argc, ...) 
  9.     int ReturnValue = 0; 
  10.     int next = 0; 
  11.     va_list arg_ptr; 
  12.  
  13.     va_start(arg_ptr, argc); 
  14.     printf("&argc = %p\n", &argc);            //打印參數i在堆棧中的地址 
  15.     printf("arg_ptr = %p\n", arg_ptr);  //打印va_start之后arg_ptr地址,比參數i的地址高sizeof(int)個字節 
  16.     /*  這時arg_ptr指向下一個參數的地址 */ 
  17.  
  18.     next = *((int*)arg_ptr); 
  19.     ReturnValue += next
  20.  
  21.     next = va_arg(arg_ptr, int); 
  22.     printf("arg_ptr = %p\n", arg_ptr);  //打印va_arg后arg_ptr的地址,比調用va_arg前高sizeof(int)個字節 
  23.  
  24.     next = *((int*)arg_ptr); 
  25.     ReturnValue += next
  26.     /*  這時arg_ptr指向下一個參數的地址 */ 
  27.     va_end(arg_ptr); 
  28.     return ReturnValue/argc; 

輸出:

  1. &argc = 0088FDD4 
  2. arg_ptr = 0088FDD8 
  3. arg_ptr = 0088FDDC 
  4. AveInt(2, 2, 4): 3 

「這個是為了介紹簡單化,所以舉的例子」

這樣有點不大方便只能獲取兩個參數的,用可變參數改變一下

  1. #include <stdio.h> 
  2. #include <stdarg.h> 
  3. int Arg_ave(int argc, ...); 
  4. void main() 
  5.     printf("Arg_ave(2, 2, 4): %d\n", Arg_ave(2, 2, 4)); 
  6.     return
  7. int Arg_ave(int argc, ...) 
  8.     int value = 0; 
  9.     int ReturnValue = 0; 
  10.  
  11.     va_list arg_ptr; 
  12.     va_start(arg_ptr, argc); 
  13.     for (int i = 0; i < argc; i++) 
  14.     { 
  15.         value = va_arg(arg_ptr, int); 
  16.         printf("value[%d]=%d\n", i + 1, value); 
  17.         ReturnValue += value; 
  18.     } 
  19.     return ReturnValue/argc; 

輸出

  1. value[1]=2 
  2. value[2]=4 
  3. Arg_ave(2, 2, 4): 3 

當你理解之后你就會說就這?這么簡單,指定第一個參數是后面參數的總數就可以了,這還不隨隨便玩

別著急,精彩的來了,「可變參數的應用」

可變參數應用:實現log打印

  1. #include <stdarg.h> 
  2. #include <stdio.h> 
  3. #include <stdlib.h> 
  4. /*定義一個回調函數指針*/ 
  5. typedef void (*libvlcFormattedLogCallback)(void* data, int level, const void* ctx, const char* message); 
  6. enum libvlc_log_level {  
  7.     LIBVLC_DEBUG = 0,       //調試 
  8.     LIBVLC_NOTICE = 2,      //普通 
  9.     LIBVLC_WARNING = 3,     //警告 
  10.     LIBVLC_ERROR = 4 }      //錯誤 
  11. /*定義一個回調函數結構體*/ 
  12. typedef struct CallbackData { 
  13.     void* managedData; 
  14.     libvlcFormattedLogCallback managedCallback; 
  15.     int minLogLevel;        //log 級別 
  16. } CallbackData; 
  17.  
  18. /*構造回調函數結構體*/ 
  19. void* makeCallbackData(libvlcFormattedLogCallback callback, void* data, int minLevel) 
  20.     CallbackData* result = (CallbackData *)malloc(sizeof(CallbackData)); 
  21.     result->managedCallback = callback; 
  22.     result->managedData = data; 
  23.     result->minLogLevel = minLevel; 
  24.     return result; 
  25.  
  26. /*回調函數*/ 
  27. void formattedLogCallback(void* data, int level, const void* ctx, const char* message) 
  28.     printf("level:%d"level); 
  29.     if (level == LIBVLC_ERROR) 
  30.     { 
  31.         printf("LIBVLC_ERROR:%s", message); 
  32.         return
  33.     } 
  34.     if (level >= LIBVLC_WARNING) { 
  35.         printf("LIBVLC_WARNING:%s", message); 
  36.         return
  37.     } 
  38.     if (level >= LIBVLC_NOTICE) 
  39.     { 
  40.         printf("LIBVLC_ERROR:%s", message); 
  41.         return
  42.     } 
  43.     if (level >= LIBVLC_DEBUG) { 
  44.         printf("LIBVLC_WARNING:%s", message); 
  45.         return
  46.     } 
  47.      
  48.      
  49.  
  50. /*和石化log信息并執行回調函數*/ 
  51. void InteropCallback(void* data, int level, const void* ctx, const char* fmt, va_list args) 
  52.     CallbackData* callbackData = (CallbackData*)data; 
  53.     if (level >= callbackData->minLogLevel) 
  54.     { 
  55.         va_list argsCopy; 
  56.         int length = 0; 
  57.  
  58.         va_copy(argsCopy, args); 
  59.         length = vsnprintf(NULL, 0, fmt, argsCopy); 
  60.         va_end(argsCopy); 
  61.  
  62.         char* str = malloc(length + 1); 
  63.         if (str != NULL
  64.         { 
  65.             va_copy(argsCopy, args); 
  66.             vsprintf(str, fmt, argsCopy); 
  67.             va_end(argsCopy); 
  68.         } 
  69.         else 
  70.         { 
  71.             // Failed to allocate log message, drop it. 
  72.             return
  73.         } 
  74.         callbackData->managedCallback(callbackData->managedData, level, ctx, str); 
  75.         free(str); 
  76.     } 
  77. void sendLog(void* data, int level, const void* ctx, const char* fmt, ...) 
  78.     va_list va; 
  79.     va_start(va, fmt); 
  80.     InteropCallback(data, level, ctx, fmt, va); 
  81.     va_end(va); 
  82. int main(int argc, char** argv) 
  83.     /*注冊一個回調函數結構體,level等級為LIBVLC_WARNING 只要發送的log等級大于等于LIBVLC_WARNING次啊會觸發回調函數*/ 
  84.     void* callbackData = makeCallbackData(formattedLogCallback, "context", LIBVLC_WARNING); 
  85.     /*發送四個等級的消息*/ 
  86.     sendLog(callbackData, LIBVLC_DEBUG, NULL"This should not be displayed : %s\n","debug"); 
  87.     sendLog(callbackData, LIBVLC_NOTICE, NULL"This should not be displayed : %s\n""notick"); 
  88.     sendLog(callbackData, LIBVLC_WARNING, NULL"This message level is : %s\n""warning"); 
  89.     sendLog(callbackData, LIBVLC_ERROR, NULL"Hello, %s ! You should see %ld message here : %s\n""World", 1, "warning message"); 
  90.  
  91.     free(callbackData); 
  92.     return 0; 

輸出                                                                                                                                                                                                                

  1. level:3LIBVLC_WARNING:This message level is : warning 
  2. level:4LIBVLC_ERROR:Hello, World ! You should see 1 message here : warning message 

這個使用示例精妙之處在于注冊一個指定level的回調函數makeCallbackData(formattedLogCallback, "context", LIBVLC_WARNING);

然后在發送log的時候根據level判斷是否執行回調函數,順便格式化log信息

 

責任編輯:武曉燕 來源: 編程學習基地
相關推薦

2011-05-13 17:25:34

C

2012-09-18 13:26:39

CC++

2009-06-29 15:23:00

2011-08-01 17:11:43

Objective-C 函數

2010-02-03 15:06:02

C++可變參數表

2023-12-04 18:31:59

C語言函數

2022-07-14 16:35:11

C語言編程語言

2010-01-15 18:50:37

C++語言

2017-04-11 08:36:09

iOS編譯應用

2022-07-01 11:56:54

C語言C++編程語言

2011-03-30 11:01:13

C語言隨機

2024-01-17 06:23:35

SwiftTypeScript定義函數

2022-01-17 07:32:34

Java參數方法

2011-06-15 10:53:05

C語言

2024-06-05 16:22:11

2010-07-12 21:44:51

HART協議

2010-02-04 13:39:44

C++數組參數

2010-12-21 14:21:36

線程C#

2010-09-08 11:59:38

藍牙協議棧

2024-08-14 18:18:47

點贊
收藏

51CTO技術棧公眾號

国产午夜精品视频免费不卡69堂| 国产真实乱子伦| 四虎视频在线精品免费网址| 欧美性猛片xxxx免费看久爱| 日本五十路在线| 欧美激情在线一区二区| 国产传媒久久久| 日韩成人午夜精品| 久久偷看各类wc女厕嘘嘘偷窃| 日韩av有码| 欧美在线观看网址综合| 日本少妇精品亚洲第一区| 亚洲人成网在线播放| 在线免费观看a视频| 欧美系列日韩一区| 日韩a级作爱片一二三区免费观看| 亚洲视频在线观看三级| 欧美成人黄色网址| 国产无遮挡一区二区三区毛片日本| 久久99久久久久久| 国产精品一区免费视频| 天堂v在线视频| 国产一区二区三区久久悠悠色av| 亚洲自拍三区| 韩国精品免费视频| 亚洲理论电影在线观看| 99久久精品费精品国产一区二区| 国产精品又粗又长| 久久影院视频免费| 污色网站在线观看| 亚洲乱码中文字幕综合| 360天大佬第二季在线观看| 亚洲精品日韩一| 久草在线资源视频| 午夜精品在线看| jizz亚洲| 日韩av一区在线| 国产激情欧美| 久精品免费视频| 欧美变态挠脚心| 国产精品一区av| 在线国产一区二区| 狠狠色综合欧美激情| 日本成人中文字幕| 日韩亚洲欧美视频| 国产无一区二区| 四色成人av永久网址| 欧美精品乱码久久久久久按摩 | 中文字幕亚洲综合久久筱田步美| 高清不卡一区| 国产精品久久久久久久一区探花 | 国产精品电影观看| 亚洲欧洲午夜| 日韩黄色片在线| 亚洲欧洲日韩av| www.亚洲免费| 一区二区三区高清国产| 外国成人在线视频| 久久精品国产一区二区三区日韩| 国产成人免费在线观看不卡| av一级毛片| 日韩免费看网站| 51精品国产| 国产伦理一区二区三区| 国产福利精品导航| а√天堂www在线а√天堂视频| 欧美精品自拍偷拍| 96视频在线观看欧美| 99re视频在线观看| 成人av在线网| 九色在线观看视频| 日韩一区二区欧美| 欧美久久久久| 亚洲成熟丰满熟妇高潮xxxxx| 欧美午夜宅男影院| a看欧美黄色女同性恋| 你懂的网址一区二区三区| 国产午夜精品福利| 黄页网站大全在线免费观看| 日本一欧美一欧美一亚洲视频| 日韩国产欧美在线播放| 97福利网站在线观看视频| 亚洲视频一区二区三区| 欧美激情自拍| 在线观看免费播放网址成人| 精品乱人伦小说| 日韩精品永久网址| 91黄色小网站| 亚洲国产精品va在看黑人| 国产精品国内免费一区二区三区| 亚洲中文字幕无码av永久| 欧美精品欧美精品系列| 亚洲丝袜美腿一区| 国产毛片视频网站| 亚洲精品一区二区三区蜜桃下载| 欧美国产美女| 精品亚洲一区二区三区四区| 亚洲午夜性刺激影院| 亚洲中字在线| 国产三级av在线| 欧美乱妇高清无乱码| 久久99国产乱子伦精品免费| 91大神在线网站| 国产精品ⅴa在线观看h| 99久久国产免费看| 91吃瓜在线观看| 精品免费一区二区三区蜜桃| 亚洲成人综合网站| 天堂99x99es久久精品免费| 成年人午夜免费视频| 精品欧美久久久| 亚洲美女一区| 视频国产一区二区三区| 国产91色在线| 国产日韩欧美a| 日韩av超清在线观看| 亚洲黄色一区二区三区| 欧美美女一区二区在线观看| 日韩欧美视频在线播放| 成人羞羞视频免费看看| 性欧美视频videos6一9| 欧美国产禁国产网站cc| 97视频一区| 永久免费的av网站| 午夜精品在线视频| 国产精品久久久久久亚洲伦| 91亚洲无吗| 日日躁夜夜躁aaaabbbb| 久久久久久久久久久免费| 久久亚洲捆绑美女| 日韩精品成人| 亚洲久久中文字幕| 日韩美女毛茸茸| 夜色激情一区二区| 日本大胆欧美| 天堂在线免费av| 97欧洲一区二区精品免费| 欧美视频在线视频| 好吊日精品视频| av软件在线观看| 欧美成人dvd在线视频| 欧美一区二区三区不卡| 免费日本视频一区| 中文字幕影音在线| aa视频在线播放| 欧美人与性动交| 中文子幕无线码一区tr| 久久91麻豆精品一区| 亚洲校园欧美国产另类| 99国产高清| 精品欧美一区二区在线观看| 国产美女主播视频一区| 日韩精品亚洲专区在线观看| 3344永久| 国产精品二区三区| 日韩精品中文字幕在线| 91蜜桃传媒精品久久久一区二区| 狼人天天伊人久久| 污污网站在线| 国产自产在线视频一区| 日韩精品在线观| 国产精品久久久久久久第一福利| 国产一区二区三区四区二区| 91社区在线高清| 韩国无码av片在线观看网站| 久久久爽爽爽美女图片| 韩曰欧美视频免费观看| 日本不卡一区二区| 视频一区视频二区欧美| 日本私人网站在线观看| 亚洲一区3d动漫同人无遮挡 | 国产精品一区二区三区不卡| 亚洲国产99精品国自产| 国产欧美日韩不卡| 午夜精品免费| 色综合一本到久久亚洲91| 国产性一级片| 五码日韩精品一区二区三区视频| 久久国产精品亚洲| 精品日本高清在线播放 | 国产精品丝袜黑色高跟| 亚洲精品国产首次亮相| 成人福利av| 在线国产1区| 精品免费久久久久久久| 国产成人啪精品视频免费网| 91精品国产入口| 久久久国际精品| 国产美女一区| 亚洲视频三区| 日本中文字幕在线观看| 国产男女激情视频| 欧美国产一二三区| 5252色成人免费视频| 亚洲国产欧美在线成人app| 亚洲女人****多毛耸耸8| 国产做a爰片久久毛片| 日韩精品影视| 久久综合给合| a国产在线视频|