簡介
一個(gè)可變參數(shù)函數(shù)是指一個(gè)函數(shù)擁有不定的參數(shù),即為一個(gè)函數(shù)可接收多個(gè)參數(shù)。有時(shí)我們會遇到一些算術(shù)問題需要用到,比如是計(jì)算傳入?yún)?shù)的總和,字符串的連接或是其它操作過程,我們在 OC 里也經(jīng)常使用,最經(jīng)典的就是 NSLog( C 為 printf ) ,它可以指定格式的輸出,格式化輸出的內(nèi)容。
舉個(gè)栗子??
新建一個(gè)類TestClass
,寫一個(gè)類方法print:
用于輸出我們傳入的值
類頭文件TestClass.h
#import <Foundation/Foundation.h>
@interface TestClass : NSObject
+ (void)print:(NSString *)firstArg, ... NS_REQUIRES_NIL_TERMINATION;
@end
類實(shí)現(xiàn)TestClass.m
#import "TestClass.h"
@implementation TestClass
+ (void)print:(NSString *)firstArg, ... NS_REQUIRES_NIL_TERMINATION {
if (firstArg) {
// 取出第一個(gè)參數(shù)
NSLog(@"%@", firstArg);
// 定義一個(gè)指向個(gè)數(shù)可變的參數(shù)列表指針;
va_list args;
// 用于存放取出的參數(shù)
NSString *arg;
// 初始化變量剛定義的va_list變量,這個(gè)宏的第二個(gè)參數(shù)是第一個(gè)可變參數(shù)的前一個(gè)參數(shù),是一個(gè)固定的參數(shù)
va_start(args, firstArg);
// 遍歷全部參數(shù) va_arg返回可變的參數(shù)(a_arg的第二個(gè)參數(shù)是你要返回的參數(shù)的類型)
while ((arg = va_arg(args, NSString *))) {
NSLog(@"%@", arg);
}
// 清空參數(shù)列表,并置參數(shù)指針args無效
va_end(args);
}
}
@end
va_list:用來保存宏 va_start 、va_arg 和 va_end 所需信息的一種類型。為了訪問變長參數(shù)列表中的參數(shù),必須聲明 va_list 類型的一個(gè)對象。
va_start:訪問變長參數(shù)列表中的參數(shù)之前使用的宏,它初始化用va_list聲明的對象,初始化結(jié)果供宏va_arg和va_end使用;
va_arg:展開成一個(gè)表達(dá)式的宏,該表達(dá)式具有變長參數(shù)列表中下一個(gè)參數(shù)的值和類型。每次調(diào)用 va_arg 都會修改,用 va_list 聲明的對象從而使該對象指向參數(shù)列表中的下一個(gè)參數(shù)。
va_end:該宏使程序能夠從變長參數(shù)列表用宏 va_start 引用的函數(shù)中正常返回。
NS_REQUIRES_NIL_TERMINATION :是一個(gè)宏,用于編譯時(shí)非nil結(jié)尾的檢查。
試一試
在外部調(diào)用一個(gè)剛剛寫的方法
注意:
- 在可變參數(shù)里,所有參數(shù)均用逗號隔開
- 參數(shù)結(jié)尾必須加上nil,表示參數(shù)結(jié)束
#import <Foundation/Foundation.h>
#import "TestClass.h"
int main(int argc, const char * argv[]) {
[TestClass print:@"a", @"b", @"c", nil];
return 0;
}
看一下執(zhí)行的結(jié)果,輸出了我們預(yù)期的值