iOS開(kāi)發(fā)中va_list的應(yīng)用

va_list的定義:

VA_LIST 是在C語(yǔ)言中解決變參問(wèn)題的一組宏曲楚,所在頭文件:#include <stdarg.h>,用于獲取不確定個(gè)數(shù)的參數(shù)。
oc中的定義如下:

#ifndef _VA_LIST
typedef __builtin_va_list va_list;
#define _VA_LIST
#endif
#define va_start(ap, param) __builtin_va_start(ap, param)
#define va_end(ap)          __builtin_va_end(ap)
#define va_arg(ap, type)    __builtin_va_arg(ap, type)

宏:

INTSIZEOF:獲取類(lèi)型占用的空間長(zhǎng)度,最小占用長(zhǎng)度為int的整數(shù)倍:
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

VA_START:獲取可變參數(shù)列表的第一個(gè)參數(shù)的地址(ap是類(lèi)型為va_list的指針,v是可變參數(shù)最左邊的參數(shù)):
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )

VA_ARG:獲取可變參數(shù)的當(dāng)前參數(shù)缘圈,返回指定類(lèi)型并將指針指向下一參數(shù)(t參數(shù)描述了當(dāng)前參數(shù)的類(lèi)型):
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

VA_END:清空va_list可變參數(shù)列表:
#define va_end(ap) ( ap = (va_list)0 )

va_list的說(shuō)明:

函數(shù)參數(shù)是存儲(chǔ)在棧中的劣光,函數(shù)參數(shù)從右往左依次入棧,參數(shù)的存儲(chǔ)如下路

va_list原理圖.png

注意:

  • 可變參數(shù)的類(lèi)型和個(gè)數(shù)完全由程序代碼控制,它并不能智能地識(shí)別不同參數(shù)的個(gè)數(shù)和類(lèi)型糟把;
  • va_start和va_end成對(duì)出現(xiàn)

va_list的應(yīng)用:

當(dāng)我們有一個(gè)需求:我們需要一個(gè)方法绢涡,但是入?yún)€(gè)數(shù)不確定,這個(gè)時(shí)候就可以使用va_list

- (void)testMethod:(NSString *)string, ...NS_REQUIRES_NIL_TERMINATION{
    va_list args;
    if (string){
        va_start(args, string);
        NSString *otherstring = nil;
        while ((otherstring = va_arg(args, NSString*))) {
            NSLog(@"string = %@ point=%p",otherstring,otherstring);
        }
        va_end(args);
    }
}

調(diào)用: [self testMethod:@"1",@"2",@"3",@(4),@"5",@"6",nil];

方法說(shuō)明:

  • NS_REQUIRES_NIL_TERMINATION告知編譯器 需要一個(gè)結(jié)尾的參數(shù),告知編譯器參數(shù)的列表已經(jīng)到最后一個(gè)不要再繼續(xù)執(zhí)行下去了遣疯。如果聲明了在調(diào)用方法時(shí)如果沒(méi)有更多的參數(shù)一定加上nil雄可,否則會(huì)一直循環(huán)取出參數(shù)造成崩潰.
  • va_start(args, string) 獲取可變參數(shù)列表的第一個(gè)參數(shù)的地址,在這里是獲取string的內(nèi)存地址,這時(shí)args的指針 指向string
  • va_arg(args, NSString*)獲取可變參數(shù)的當(dāng)前參數(shù),返回指定類(lèi)型并將指針指向下一參數(shù),第一次循環(huán)就會(huì)把指針指向上圖的p2,下一次就會(huì)指向p3.直到結(jié)束缠犀,什么時(shí)候結(jié)束呢数苫?如果我們不判斷篩選條件,可以一直取出數(shù)據(jù)辨液,我們通常直到內(nèi)存空間取到數(shù)據(jù)為nil時(shí)或者0時(shí)結(jié)束虐急。
  • va_arg(args, NSString*)中會(huì)將指針指向下一參數(shù),那應(yīng)該偏移多少是到下一個(gè)參數(shù)地址呢滔迈?會(huì)等于與va_arg宏所返回的數(shù)值具有相同類(lèi)型的對(duì)象的長(zhǎng)度止吁,比如:都是NSString類(lèi)型,這時(shí)候偏移8字節(jié)燎悍,如果參數(shù)中混有其他類(lèi)型的數(shù)據(jù)敬惦,如int,這時(shí)候偏移8字節(jié)能取到正確的數(shù)據(jù)嗎谈山,肯定是有問(wèn)題的俄删,所以當(dāng)我們?cè)趥鲄?shù)時(shí),多個(gè)參數(shù)的類(lèi)型要盡量一樣

系統(tǒng)的NSLog也是用到va_list勾哩,va_list不會(huì)知道我們參數(shù)的數(shù)據(jù)類(lèi)型和個(gè)數(shù)抗蠢,這就是為什么我們需要占位符的原因

FOUNDATION_EXPORT void NSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2) NS_NO_TAIL_CALL;

所以va_list很傻举哟,很不智能.......

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末思劳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子妨猩,更是在濱河造成了極大的恐慌潜叛,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壶硅,死亡現(xiàn)場(chǎng)離奇詭異威兜,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)庐椒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)椒舵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人约谈,你說(shuō)我怎么就攤上這事笔宿±缰樱” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵泼橘,是天一觀的道長(zhǎng)涝动。 經(jīng)常有香客問(wèn)我,道長(zhǎng)炬灭,這世上最難降的妖魔是什么醋粟? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮重归,結(jié)果婚禮上米愿,老公的妹妹穿的比我還像新娘。我一直安慰自己鼻吮,他們只是感情好吗货,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著狈网,像睡著了一般宙搬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拓哺,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天勇垛,我揣著相機(jī)與錄音,去河邊找鬼士鸥。 笑死闲孤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的烤礁。 我是一名探鬼主播讼积,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼脚仔!你這毒婦竟也來(lái)了勤众?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鲤脏,失蹤者是張志新(化名)和其女友劉穎们颜,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體猎醇,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡窥突,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了硫嘶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阻问。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖沦疾,靈堂內(nèi)的尸體忽然破棺而出称近,到底是詐尸還是另有隱情贡蓖,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布煌茬,位于F島的核電站斥铺,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏坛善。R本人自食惡果不足惜晾蜘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望眠屎。 院中可真熱鬧剔交,春花似錦、人聲如沸改衩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)葫督。三九已至竭鞍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間橄镜,已是汗流浹背偎快。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留洽胶,地道東北人晒夹。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像姊氓,于是被迫代替她去往敵國(guó)和親丐怯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容