Objective-C中可選參數(shù)的實(shí)現(xiàn)

代碼:


-(NSString*)makeDrink:(NSString*)drink Fruit:(NSString*)fruit Food:(NSString*)foodOne,...;

{

NSMutableArray* arr = [[NSMutableArrayalloc]init];

va_listparams;

idargument;

if(foodOne) {

va_start(params, foodOne);

while((argument =va_arg(params,id))) {

[arraddObject:argument];

}

va_end(params);

}

returnnil;

}

------------------------------------------------------------

用法:


Person *man = [Person alloc] init];

[man makeDrink:@"beer" Fruit:@"banana" Food:@"rice",@"beef",@"fish",@"potato",@"vegetables",nil];

------------------------------------------------------------

知識點(diǎn):


va_list/va_start/va_arg/va_end這幾個宏闯传,都是用于函數(shù)的可變參數(shù)的缺狠。

我們來看看在vs2008中,它們是怎么定義的:

1:///stdarg.h

2:#defineva_start _crt_va_start

3:#defineva_arg _crt_va_arg

4:#defineva_end _crt_va_end

5:

6:///vadefs.h

7:#define_ADDRESSOF(v)? ( &reinterpret_cast(v) )

8:? typedefchar*? va_list;

9:#define_INTSIZEOF(n)? ( (sizeof(n) +sizeof(int) - 1) & ~(sizeof(int) - 1) )

10:#define_crt_va_start(ap,v)? ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )

11:#define_crt_va_arg(ap,t)? ? ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

12:#define_crt_va_end(ap)? ? ? ( ap = (va_list)0 )


代碼原圖


再看看各個宏的功能是什么忍饰?

va_list用于聲明一個變量,我們知道函數(shù)的可變參數(shù)列表其實(shí)就是一個字符串垦沉,所以va_list才被聲明為字符型指針迫皱,這個類型用于聲明一個指向參數(shù)列表的字符型指針變量,例如:va_list ap;//ap:arguement pointer

va_start(ap,v),它的第一個參數(shù)是指向可變參數(shù)字符串的變量沸版,第二個參數(shù)是可變參數(shù)函數(shù)的第一個參數(shù),通常用于指定可變參數(shù)列表中參數(shù)的個數(shù)兴蒸。

va_arg(ap,t),它的第一個參數(shù)指向可變參數(shù)字符串的變量视粮,第二個參數(shù)是可變參數(shù)的類型。

va_end(ap) 用于將存放可變參數(shù)字符串的變量清空(賦值為NULL).

va_start的功能是要把橙凳,ap指針指向可變參數(shù)的第一個參數(shù)位置處蕾殴,

#define_crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )

先取第一個參數(shù)的地址,在sum函數(shù)中就是取number的地址并且將其轉(zhuǎn)化為char *的(因?yàn)閏har *的指針進(jìn)行加減運(yùn)算后岛啸,偏移的字節(jié)數(shù)才與加的數(shù)字相同, 如果為int *p,那么p+1實(shí)際上將p移動了4個字節(jié))区宇,然后加上4(__INITSIZEOF(number)=(4+3)&~3),這樣就將ap指向了可變參數(shù)字符串的第一個參數(shù)值戳。

#define_INTSIZEOF(n) ( (sizeof(n) +sizeof(int) - 1) & ~(sizeof(int) - 1) )

以int所占的字節(jié)為標(biāo)準(zhǔn)進(jìn)行對其操作议谷。

如果int占四字節(jié),則以四字節(jié)對齊為標(biāo)準(zhǔn)讀取數(shù)據(jù)堕虹。

va_arg是要從ap中取下一個參數(shù)卧晓。

#define_crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

對于這個宏,哥糾結(jié)了很久赴捞,最后終于搞清楚了逼裆,究其原因就是自己C語言功底不扎實(shí),具體表現(xiàn)在沒有搞清楚賦值表達(dá)式的值是怎么運(yùn)作的赦政。

我們看這個宏,首先是ap = ap + __INTSIZEOF(t)胜宇。注意到,此時ap已經(jīng)被改變了恢着,它已經(jīng)指向了下一個參數(shù)桐愉,我們令x=ap + __INTSIZEOF(t);

那么括號內(nèi)就變成了(x – __INTSIZEOF(t)),但是這里沒有賦值運(yùn)算符掰派,所以ap的值沒有發(fā)生變化从诲,此時ap仍然指向的是當(dāng)前參數(shù)的下一個參數(shù)的位置,

也就是說ap指向的位置比當(dāng)前正在處理的位置超前了一個位置靡羡。

其實(shí)寫成下面的形式就簡單明了了:

#define?? va_arg(ap,t)?? (*(t?? *)((ap?? +=?? _INTSIZEOF(t)),ap?? -?? _INTSIZEOF(t)))

分析:為什么要將ap指向當(dāng)前處理參數(shù)的下一個參數(shù)了系洛?

經(jīng)過上面的分析俊性,我們知道va_start(ap,v)已經(jīng)將ap指向了可變參數(shù)列表的第一個參數(shù)了,以后我們每一步操作都需要將ap移動到下一個

參數(shù)的位置描扯,由于我們每次使用可變參數(shù)的順序是:va_start(ap,v)—>va_arg(ap,t)定页;這樣我們在第一次去參數(shù)的時候,其實(shí)ap已經(jīng)指向了

第二個參數(shù)開始的位置绽诚,所以我們用表達(dá)式的方式獲得一個指向第一個參數(shù)的臨時指針典徊,這樣我們就可以采用這種一致的方式來處理可變參數(shù)列表。

(感覺沒表達(dá)的十分清楚憔购,希望各位朋友糾正~~~~~~)宫峦。

下圖是我的例子程序中去參數(shù)的情況(時間倉促岔帽,畫得很丑玫鸟,請?jiān)彛?/p>

va_end(ap)? 將聲明的ap指針置為空,因?yàn)橹羔樖褂煤笞詈笤O(shè)置為空犀勒。

參考資料:

http://topic.csdn.net/u/20110830/15/a3630fc4-3c5f-4a1e-bbee-949ba7b4cbe0.html

http://topic.csdn.net/u/20070120/12/e8b7363b-6404-4d91-9307-01e5ed996f3d.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末屎飘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子贾费,更是在濱河造成了極大的恐慌钦购,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件褂萧,死亡現(xiàn)場離奇詭異押桃,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)导犹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門唱凯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谎痢,你說我怎么就攤上這事磕昼。” “怎么了节猿?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵票从,是天一觀的道長。 經(jīng)常有香客問我滨嘱,道長峰鄙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任太雨,我火速辦了婚禮先馆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘躺彬。我一直安慰自己煤墙,他們只是感情好梅惯,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著仿野,像睡著了一般铣减。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上脚作,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天葫哗,我揣著相機(jī)與錄音,去河邊找鬼球涛。 笑死劣针,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亿扁。 我是一名探鬼主播捺典,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼从祝!你這毒婦竟也來了襟己?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤牍陌,失蹤者是張志新(化名)和其女友劉穎擎浴,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毒涧,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贮预,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了契讲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仿吞。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖怀泊,靈堂內(nèi)的尸體忽然破棺而出茫藏,到底是詐尸還是另有隱情,我是刑警寧澤霹琼,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布务傲,位于F島的核電站,受9級特大地震影響枣申,放射性物質(zhì)發(fā)生泄漏售葡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一忠藤、第九天 我趴在偏房一處隱蔽的房頂上張望挟伙。 院中可真熱鬧,春花似錦模孩、人聲如沸尖阔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽介却。三九已至谴供,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間齿坷,已是汗流浹背桂肌。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留永淌,地道東北人崎场。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像遂蛀,于是被迫代替她去往敵國和親谭跨。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345

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