可变参数、不定参数(va_list、va_start、va_arg、va_end)

可变参数、不定参数是什么

我这里所说的可变参数或不定参数是指, 方法中的某个形式参数可以接收多个参数(不确定个数的参数)。就比如, 下面的一些系统的方法:

[NSArray arrayWithObjects:@"first", @"second", @"third"];
[[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:nil cancelButtonTitle:@ otherButtonTitles:@"first", @"second", @"third", nil];

// Method Reference

+ (instancetype)arrayWithObjects:(ObjectType)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
- (instancetype)initWithTitle:(nullable NSString *)title message:(nullable NSString *)message delegate:(nullable id /*<UIAlertViewDelegate>*/)delegate cancelButtonTitle:(nullable NSString *)cancelButtonTitle otherButtonTitles:(nullable NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION

以上这两个方法都是系统的方法, NSArray方法中的firstObjUIAlertView方法中的otherButtonTitles都是可变参数。

实现可变参数的方法

自定义一个方法printMessages: 实现可变参数:

- (void)printMessages:(nullable NSString *)messages, ... NS_REQUIRES_NIL_TERMINATION {
    if (messages) {
        // 取出第一个参数(这是固定参数)
        NSLog(@"固定参数: %@", messages);
        // 定义一个参数列表指针
        va_list args;
        // 存放所取参数的指针
        NSString *arg;
        // 初始化va_list变量
        va_start(args, messages);
        // 取出va_list中存储的可变参数(不包含固定参数), 取出后args指向参数列表中的下一个参数
        while ((arg = va_arg(args, NSString *))) {
            NSLog(@"可变参数: %@", arg);
        }
        // 清空参数列表,并将va_list的指针置为NULL
        va_end(args);
    }
}

调用方法:

   [self printMessages:@"first", @"second", @"third", nil];

打印结果:

固定参数: first
可变参数: second
可变参数: third

实现可变参数的原理

在上面的代码中, 读取可变参数的过程其实就是在堆栈中,使用指针, 遍历堆栈段中的参数列表, 从低地址到高地址一个一个地把参数内容读出来的过程。

归根到底还是通过 va_listva_startva_argva_end 这四个宏的功能来实现的。它们就是C语言中用来解决变参问题的一组宏。

它们的具体作用如下:
va_list: 用于获取不确定个数的参数, 保存宏 va_startva_argva_end 所需信息的一种类型。为了访问可变参数列表中的参数,必须声明一个 va_list类型的指针。
va_start: 初始化 va_list,获取可变参数列表的第一个参数的地址。初始化结果供宏va_argva_end使用。
va_arg: 获取可变参数的当前参数,返回指定类型并将指针指向下一参数
va_end: 清空va_list可变参数列表,并该指针置为NULL

Demo下载地址:
Demo
拓展资料:
va_listva_startva_argva_end

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页