亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Linux下C庫學習 - stdarg.h

2019-11-10 20:43:02
字體:
來源:轉載
供稿:網友

想要函數使用可變參數,那就必須要包含stdarg.h這個頭文件,簡單就不說了,我們重新來看看可變參數的定義和使用吧。

1.聲明可變參數

可變參數的聲明有兩點

使用‘…’來代表可變參數可變參數之前必須有一個命名的參數

簡單說就是如果你想聲明一個可變參數的函數,那么有兩種形式

func(...) //錯誤,前面必須有一個命名的參數func(xxx,...) //正確,xxx可以用任意的參數代替,比如char *name,int i都可以

2.定義可變參數

可變參數的定義和聲明相同,兩者保持一致即可

3.可變參數的使用

要使用可變參數,主要會用到下列幾個函數

#include <stdarg.h>void va_start(va_list ap, last);type va_arg(va_list ap, type);void va_end(va_list ap);void va_copy(va_list dest, va_list src);

這里四個函數是參考man手冊上的,最后的va_copy沒有用過,不太清楚什么情況下需要使用,麻煩各位在留言賜教 剩下的三個我們來一個一個看,這里舉個簡單的例子方便講解

#include <stdio.h>#include <stdarg.h>void fun(char *name, ...){ va_list pa; int a, b; char *c; double d; va_start(pa, name); a = va_arg(pa, int); b = va_arg(pa, int); c = va_arg(pa, char *); d = va_arg(pa, double); va_end(pa); 可以看到,要使用可變參數,首先需要定義一個va_list類型的變量,這個變量就相當于是指向可變參數列表的指針,通過va_start函數將這個指針賦值,后面就可以通過va_arg來獲取每一個參數。

va_arg的函數原型里面有個type,這個type類型怎么理解呢? 大家可以這樣理解,因為可變參數是沒有聲明參數類型的,那么編譯器怎么去檢測到底類型是否匹配呢?最簡單的辦法就是向上提升,比如

float類型的實際參數將提升到doublechar、short和相應的signed、unsigned類型的實際參數提升到int如果int不能存儲原值,則提升到unsigned int

由于默認肯定會向上提升,所以一定要盡量避免以下類型的參數 type絕對不能為以下類型:

char、signed char、unsigned charshort、unsigned shortsigned short、short int、signed short int、unsigned short intfloat

因此在示例中,第一個int類型的數字我用int類型接收,第二個字符我依然使用int類型來接收,第三個字符串就必須使用char *類型的接收,第四個浮點型使用double類型來接收,如果你不小心寫錯了類型,系統的提示如下(這里我把示例中的double改成了float)

test.c: In function ‘fun’:test.c:17:20: warning: ‘float’ is promoted to ‘double’ when passed through ‘...’ [enabled by default] d = va_arg(pa, float); ^test.c:17:20: note: (so you should pass ‘double’ not ‘float’ to ‘va_arg’)test.c:17:20: note: if this code is reached, the program will abort

最后的va_end就相當于是結束標記,一個va_start必須和一個va_end對應起來使用才可以。

使用的話我想大家應該都會,那具體原理是什么樣的呢? 要搞清楚原理,首先需要知道參數到底是怎么傳遞進來的,事實上,在進程中,堆棧地址時由高向低分配的,在調用參數的時候,首先入棧的函數參數,接下來是函數的返回地址,再下來是函數的執行代碼,而參數的入棧順序是先入最后一個參數,最后入第一個參數

這里寫圖片描述

如上圖所示,參數在堆棧的排列是從高地址向低地址的,實際上具體是宏定義如下

typedef char * va_list; // x86平臺下va_list的定義#define va_start(ap, v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一個可選參數地址#define va_arg(ap, t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一個參數地址#define va_end(ap) ( ap = (va_list)0 ) // 將指針置為無效

這里有個宏_INTSIZEOF需要特別介紹下,這個宏是為了求出變量所占內存空間的大小,具體實現如下

#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

網上有位大神對這個函數又深刻的理解,大家可以去看看他的文章_INTSIZEOF(n)這個函數簡單說就是把n轉化成int的整數倍,來實現格式對齊,明白了這里,我們接著往下看

va_start 這個應該很好理解,就是說固定參數的地址加上他本身的內存大小,結合上面的圖也就是第一個可變參數的地址,這樣ap就指向了第一個可變參數,后面我們通過ap就可以得到其他的參數

va_arg 這個宏寫的有些復雜,我們需要把它拆成兩部分看 1. ap += _INTSIZEOF(t); // 此時指針ap已經指向下一個參數了 /* ap減去當前參數的大小得到當前參數的地址,再把地址強制類型轉換后返回它的值 */ 2. return (t )( ap - _INTSIZEOF(t)) 通過第一步我們讓指針ap指向了后一個參數,通過第二步返回了當前的參數

va_end 這個宏很簡單,就是清空了指針,記著需要和va_start配套使用

看了C語言的具體實現,不得不感嘆,大神們真的是把指針使用的淋漓盡致,不過任何事情都有兩方面,這樣做雖然高效快捷,但同時也留下了不小的安全隱患

參考文檔 深入淺出va函數 關于va_arg中的type


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美中文字幕在线| 日本久久久a级免费| 久久久成人的性感天堂| 日韩av电影在线免费播放| 国产精品ⅴa在线观看h| 尤物yw午夜国产精品视频明星| 国产97色在线|日韩| 性欧美xxxx| 国产精品免费看久久久香蕉| 91日本在线观看| 国产成人精品在线| 亚洲国产天堂久久综合| 久久免费精品日本久久中文字幕| 91久久精品在线| 日韩视频在线观看免费| 国产精品揄拍500视频| 欧美日韩亚洲精品内裤| 午夜免费在线观看精品视频| 久久精品在线播放| 国产精品国产三级国产专播精品人| 91精品视频一区| 国产91精品久| 日韩精品视频在线| 免费91麻豆精品国产自产在线观看| 欧美诱惑福利视频| 亚洲精品成a人在线观看| 亚洲色图美腿丝袜| 青青草一区二区| 日本一区二区不卡| 亚洲美腿欧美激情另类| 神马久久桃色视频| 日韩免费观看高清| 91精品国产91久久| 国产原创欧美精品| 日韩女优在线播放| 久久亚洲国产精品成人av秋霞| 亚洲欧美在线第一页| 在线午夜精品自拍| 亚洲女同性videos| 国产精品成人av性教育| 国产精品午夜一区二区欲梦| 成人av番号网| 久久五月天综合| 大桥未久av一区二区三区| 国产精品中文久久久久久久| 日韩精品一区二区三区第95| 欧美激情一区二区三级高清视频| 国产午夜一区二区| 综合网日日天干夜夜久久| 国产精品扒开腿做爽爽爽的视频| 欧美日韩美女在线| 5278欧美一区二区三区| 国产日产欧美a一级在线| 亚洲激情在线观看视频免费| 国产亚洲精品va在线观看| 菠萝蜜影院一区二区免费| 欧美视频在线观看 亚洲欧| 色偷偷888欧美精品久久久| 欧美大学生性色视频| 欧美孕妇孕交黑巨大网站| 精品国产依人香蕉在线精品| 久久人体大胆视频| 日韩精品在线电影| 萌白酱国产一区二区| 中文日韩在线视频| 这里只有精品丝袜| 欧美在线精品免播放器视频| 亚洲第一网中文字幕| 欧美日韩国产页| 欧美性xxxx极品hd欧美风情| 国产丝袜高跟一区| 国产日产欧美a一级在线| 欧美怡红院视频一区二区三区| 日韩a**站在线观看| 色久欧美在线视频观看| 欧美自拍大量在线观看| 91亚洲国产成人久久精品网站| 成人a在线视频| 亚洲第一福利在线观看| 国产精品三级美女白浆呻吟| 中文字幕亚洲字幕| 庆余年2免费日韩剧观看大牛| 亚洲最大的免费| 最近2019年好看中文字幕视频| 国产欧美日韩免费看aⅴ视频| 456国产精品| 亚洲石原莉奈一区二区在线观看| 蜜月aⅴ免费一区二区三区| 亚洲天堂久久av| 最近日韩中文字幕中文| 亚洲成年人影院在线| 亚洲aⅴ日韩av电影在线观看| 亚洲美女在线观看| 亚洲区在线播放| 亚洲国产日韩欧美在线动漫| 青青草一区二区| 韩国国内大量揄拍精品视频| 国产玖玖精品视频| 91精品国产91久久久久久最新| 国产成人极品视频| 国产欧美最新羞羞视频在线观看| 精品毛片三在线观看| 久久久av亚洲男天堂| 欧美小视频在线| 久久免费视频网| 久久福利网址导航| 成人精品久久av网站| 亚洲欧美资源在线| 成人免费网视频| 91青草视频久久| 国产日韩欧美黄色| 精品国产一区二区三区在线观看| 久久久久久久电影一区| 91免费人成网站在线观看18| 国产精品网站入口| 欧美日韩国产丝袜美女| 欧美麻豆久久久久久中文| 欧美午夜精品久久久久久人妖| 亚洲精品女av网站| 国产精品免费小视频| 欧美电影第一页| 亚洲性视频网址| 日韩精品免费一线在线观看| 国产精品视频公开费视频| 欧美大片在线免费观看| 久久久噜噜噜久久久| 亚洲人a成www在线影院| 欧美午夜精品伦理| 欧美性理论片在线观看片免费| 久久精品精品电影网| 欧美极品少妇全裸体| 久久精品免费电影| 国产欧美日韩免费| 色综合久久久久久中文网| xxxxx成人.com| 国产欧美日韩专区发布| 国产精品jizz在线观看麻豆| 亚洲人av在线影院| 日韩av免费观影| 亚洲国产精久久久久久久| 欧美肥臀大乳一区二区免费视频| 日韩精品免费一线在线观看| 性欧美办公室18xxxxhd| 黑人狂躁日本妞一区二区三区| 欧美专区在线播放| 欧美日韩中文字幕在线| 国产美女精品视频免费观看| 黑人巨大精品欧美一区二区一视频| 深夜福利亚洲导航| 欧美激情在线播放| 日韩在线欧美在线国产在线| 日韩电影视频免费| 国产伦精品一区二区三区精品视频| 亚洲色图美腿丝袜| 日韩在线免费高清视频| 亚洲人成在线观| 成人黄色片网站| 国产精品大陆在线观看| 欧美成人四级hd版| 欧美理论电影在线观看| 色综合导航网站| 韩日欧美一区二区| 精品国产一区二区三区久久久| 久久天天躁狠狠躁老女人|