Objective-C中可選參數的實現

代碼:


-(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];

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

知識點:


va_list/va_start/va_arg/va_end這幾個宏,都是用于函數的可變參數的。

我們來看看在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用于聲明一個變量,我們知道函數的可變參數列表其實就是一個字符串,所以va_list才被聲明為字符型指針,這個類型用于聲明一個指向參數列表的字符型指針變量,例如:va_list ap;//ap:arguement pointer

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

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

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

va_start的功能是要把,ap指針指向可變參數的第一個參數位置處,

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

先取第一個參數的地址,在sum函數中就是取number的地址并且將其轉化為char *的(因為char *的指針進行加減運算后,偏移的字節數才與加的數字相同, 如果為int *p,那么p+1實際上將p移動了4個字節),然后加上4(__INITSIZEOF(number)=(4+3)&~3),這樣就將ap指向了可變參數字符串的第一個參數。

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

以int所占的字節為標準進行對其操作。

如果int占四字節,則以四字節對齊為標準讀取數據。

va_arg是要從ap中取下一個參數。

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

對于這個宏,哥糾結了很久,最后終于搞清楚了,究其原因就是自己C語言功底不扎實,具體表現在沒有搞清楚賦值表達式的值是怎么運作的。

我們看這個宏,首先是ap = ap + __INTSIZEOF(t)。注意到,此時ap已經被改變了,它已經指向了下一個參數,我們令x=ap + __INTSIZEOF(t);

那么括號內就變成了(x – __INTSIZEOF(t)),但是這里沒有賦值運算符,所以ap的值沒有發生變化,此時ap仍然指向的是當前參數的下一個參數的位置,

也就是說ap指向的位置比當前正在處理的位置超前了一個位置。

其實寫成下面的形式就簡單明了了:

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

分析:為什么要將ap指向當前處理參數的下一個參數了?

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

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

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

(感覺沒表達的十分清楚,希望各位朋友糾正~~~~~~)。

下圖是我的例子程序中去參數的情況(時間倉促,畫得很丑,請原諒):

va_end(ap)? 將聲明的ap指針置為空,因為指針使用后最后設置為空。

參考資料:

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,835評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,676評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,730評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,118評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,873評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,266評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,330評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,482評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,036評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,846評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,025評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,575評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,279評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,684評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,953評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,751評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,016評論 2 375

推薦閱讀更多精彩內容