`
evolxb
  • 浏览: 9437 次
社区版块
存档分类
最新评论

obj-c中的可变参数

 
阅读更多

Objective-C 中有许多不定参数函数,像 NSLog(format, arg1, arg2),还有字符串或数组在构造时所用的 [NSString stringWithFormat: format, arg1, arg2, arg3],它们的方法原型分别是:

FOUNDATION_EXPORT void NSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
+ (id)stringWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2);

应该去掉后面的 NS_FORMAT_FUNCTION(1,2) 来看,否来会干扰到思维。我们现在的例子还不需要这么写,至于 NS_FORMAT_FUNCTION(1,2) 的功用为何,我有时间还得好生看下。OK, 看多了 Apple 的那些可变参函数,可能反而令你感到费解,还不如来试个实际的例子:

- (void)foo:(NSString *)format, ...
{
    va_list args;
    va_start(args, format);
    NSString *str = [[NSString alloc] initWithFormat:format arguments:args];
    va_end(args);

    printf([str UTF8String]);

    [str release];
} 

- (IBAction) doo: (UIButton*) sender
{
    //须留意不定参函数的调用格式,逗号分隔的序列,应该它们整体是作为函数的一个参数传入
    [self foo : @"My name %@, %@", @"Unmi", @"Yes"];
}

上面的代码我未加注释,演示的是点击界面某个按钮来触发执行的,调用 NSString 的 initWithFormat 把传入的格式字符串及后面不定数量的参数拼接成一个字符串,然后打印出:

My name Unmi, Yes

到现了,已经有个体验了,也看到 va_list,va_start,va_end 那几个西正是处理不定参数的关键元件。下面要稍加深入去理解它们了。

现在重写前面的 foo 方法:

- (void)foo:(NSString *) format, ...
{   
    NSString* eachArg;
    va_list argList;
    if (format)                      // 第一个参数 format 是不属于参数列表的,
    {                                  
        va_start(argList, format);          // 从 format 开始遍历参数,不包括 format 本身.
        while (eachArg = va_arg(argList, NSString*)) // 从 args 中遍历出参数,NSString* 指明类型
            NSLog(@"%@",eachArg);              // 打印出每一个参数.
        va_end(argList);
    }
}

可以逐个打印出第一个之后的参数,如:

2011-06-17 02:05:28.840 Ohh[21874:40b] Unmi
2011-06-17 02:05:31.279 Ohh[21874:40b] Yes

每一个参数都能处理,那接下来自己写更复杂的类似函数不会有什么问题了,不定参数可以指定任何实际的类型,(id) 可真是任何类型了。

跟 Java 的不定参函数一样,不定的那些参数最终是作为函数的一个数组参数,Objective-C 的那堆参数也是变成函数的一个参数 args 参数列表。而且同样的,Objective-C 的不定参数,即 ... 也必须放在函数的最后面,如还有其他参数时,foo 要写成:

- (void)foo: state: (BOOL) enable withFormat: (NSString *)format, ...

而不能是:

- (void)foo: format: (NSString *)format, ... withState: (BOOL) enable

最后那几个关键件要说明一下:

va_list argList:定义一个指向个数可变的参数列表指针;
va_start(argList,statement):使参数列表指针arg_ptr指向函数参数列表中的第一个可选参数,说明:argN是位于第一个可选参数之前的固定参数,(或者说,最后一个 固定参数;…之前的一个参数),函数参数列表中参数在内存中的顺序与函数声明时的顺序是一致的。如果有一va函数的声明是void va_test(char a, char b, char c, …),则它的固定参数依次是a,b,c,最后一个固定参数argN为c,因此就是va_start(arg_ptr, c)。
va_arg(argList,id):返回参数列表中指针arg_ptr所指的参数,返回类型为type,并使指针arg_ptr指向参数列表中下一个参数。
va_end(arg_ptr):清空参数列表,并置参数指针arg_ptr无效。

在调用的时候要在参数结尾的时候加 nil,回想下 [NSMutableArray arrayWithObjects: 1, 2, 3, nil] 这个构造过程,最后一个 nil 能让 va_arg 取参数时碰到 nil 则断定为 NO,终止循环。为何像 NSLog 调用不需要最后一个 nil?

分享到:
评论

相关推荐

    From C++ to Objective-C

    - **可变参数列表**:Objective-C支持可变参数列表的方法。 - **匿名参数**:在Objective-C中,可以通过省略参数名称来实现匿名参数。 - **方法修饰符**:包括`const`、`static`、`virtual`等关键字,用于修饰方法的...

    Object-C复习_object-c_复习_

    Objective-C(简称Obj-C)是一种基于C语言的、面向对象的编程语言,主要用于苹果的iOS和macOS操作系统开发。作为Apple的首选编程语言,理解并熟练掌握Objective-C对于iOS和macOS应用开发至关重要。本复习资料旨在...

    Object-C期末复习_object-c_

    - 实现这些协议的对象可以被复制,`NSCopying`创建不可变副本,`NSMutableCopying`创建可变副本。 10. **GCD(Grand Central Dispatch)**: - GCD是Apple的多线程解决方案,用于并行执行任务,提高应用程序性能...

    解析Java的可变长参数列表及其使用时的注意点

    可变参数必须是方法参数列表中的最后一个参数,不能有其他参数在其后面。例如,你不能有`void method(int a, Object... b, String c)`这样的定义。 3. **传参灵活性**: 在调用使用可变参数的方法时,你可以传递...

    From C++ to Objective-C.pdf

    - **利用官方文档**: Apple官方文档提供了详细的Objective-C和Cocoa框架的教程和参考,是学习过程中不可或缺的资源。 #### 结论 Objective-C作为一种强大的面向对象编程语言,在苹果生态系统中扮演着重要角色。...

    Object-C数组排序

    在Objective-C中,数组操作是常见的编程任务,特别是在iOS和macOS开发中。数组排序是数据处理的关键部分,它能够帮助我们有效地组织和检索数据。本篇将详细讲解Object-C中的数组排序,以及如何实现一个简洁易懂的...

    C语言考试题C语言考试题.docx

    这里的关键在于`const`修饰的是`char`而不是`*ps`,即指针所指向的内容是不可变的,但指针本身可以指向其他地方。 #### 13. 数组声明 **题目描述**:在以下定义中,正确的说明语句是什么? - **选项分析**: - A. ...

    C语言课件-C对C的扩充PPT优秀资料.ppt

    编译过程分为编译和链接两个步骤,编译器将源文件编译成目标文件(如`.obj`),然后链接器将目标文件与库文件链接生成可执行文件。 C++的I/O流库是基于流的概念,它提供了一种抽象的数据传输机制,使得输入输出操作...

    在keil上实现C与汇编混合编程

    在嵌入式系统开发领域,特别是在基于51单片机的应用中,为了提高程序执行效率并充分利用硬件资源,混合编程技术变得尤为重要。混合编程指的是在同一项目中同时使用C语言和汇编语言进行编程。这种做法结合了C语言易于...

    C语言详细笔记——学习C语言从此变得简单

    - **数据符号**:C语言中常用的数据符号包括 `%d`、`%f` 和 `%c` 等,分别用于输出不同的数据类型。 - **ASCII码**:ASCII码是字符编码的一种标准,用以表示字母、数字等符号。例如,大写字母“A”的ASCII码为65,...

    Fortran混合编程.ppt

    3. **参数数目是否可变**:是否支持可选参数。 4. **参数数据类型**:如整型、浮点型、字符型等。 #### 五、命名约定 命名约定用于确保不同语言之间对象的正确识别。它包括变量名称、例程名称、模块名称等。混合...

    Blocks 编程要点

    3. **可变性:** 捕获的变量可以是常量也可以是可变变量,这取决于 Blocks 如何声明和使用它们。 4. **线程安全性:** Blocks 支持跨线程调用,这使得它们非常适合用于异步编程模型。 5. **内存管理:** Blocks 自带...

    《C语言程序设计》复习 参考答案.pdf

    - 常量:值不可变的量,如数字123、字符'A'、浮点数3.14等。 - 变量:值可变的量,需要先声明再使用,如`int x = 10;`。 6. **运算符与表达式**: - 包括算术运算符(+、-、*、/、%)、关系运算符(==、!=、<、>...

    单片机C语言实例--73-看门狗溢出测试.zip

    C语言在单片机编程中提供了丰富的控制结构和数据类型,使得编写复杂逻辑的看门狗测试程序变得更为便捷。 "看门狗溢出测试.c" 文件很可能是本次实例的主要源代码,它包含了对看门狗定时器的初始化、设置、以及在程序...

    Class(类类型),Selector(选择器SEL),函数指针(IMP)

    IMP是Objective-C中表示方法实现的函数指针类型,它指向一个C语言风格的函数,该函数的参数和返回值与被调用的方法相同。当你有一个选择器,你可以通过`class_getMethodImplementation`函数获取对应的选择器的IMP,...

    高级PHP之《高级语法》

    #### 2.7 可变参数和可变参数表单 可变参数允许函数接受任意数量的参数。可变参数表单则是在函数调用时传递多个参数的一种方式。 **示例代码** (可变参数): ```php function sum() { $total = 0; foreach (func_...

    haXe2语言参考手册(英文)

    - 定义不可变的数据。 - 示例: `const myConst:Int = 10;` - **运算符** (`Operations`): - 支持算术、比较、逻辑等操作。 - 示例: `+`, `-`, `*`, `/`, `, `>`, `==`, `!=`, `&&`, `||`. - **一元运算** (`...

    C语言程序设计方案PPT学习教案.pptx

    - **常量**: 不可变的值,C语言中的常量包括整型常量、浮点型常量、字符常量和字符串常量。 5. **函数**: - **函数**: 封装了特定任务的代码块,可以被多次调用。函数定义包括函数名、返回类型、参数列表和函数...

    iOS模型数组排序

    如果你希望原地排序(即改变原始数组),可以使用`sortUsingComparator:`方法,但是要注意,对于不可变的`NSArray`,这个方法是不适用的,因为`NSArray`是不可变的,你需要先将其转换为可变的`NSMutableArray`。...

    oc数组排序

    `NSArray`是不可变的,一旦创建就不能修改,而`NSMutableArray`则支持添加、删除和替换元素等操作,因此更适合需要排序的情况。 创建一个`NSArray`的基本语法如下: ```objc NSArray *myArray = @[@"Element1", @...

Global site tag (gtag.js) - Google Analytics