为什么80%的码农都做不了架构师?>>>   

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?

参考:

1. 关于可变参数函数的定义
2. Object c-可变参数函数的定义

转载于:https://my.oschina.net/u/865478/blog/290516

Obejctive-C 中定义可变参函数相关推荐

  1. c语言头文件中定义inline static相关函数的优劣

    头文件中常见static inline函数,于是思考有可能遇到的问题,如头文件经常会被包含会不会产生很多副本?网上说法不一.于是自己验证.经过arm-none-eabi-gcc下测试后得出结论. in ...

  2. iOS asset 中定义颜色,xib中便捷访问

    在aseet 中定义一个颜色 这样就可以在xib 中访问颜色了,这样就不用重复的去输入

  3. 主键SQL教程–如何在数据库中定义主键

    Every great story starts with an identity crisis. Luke, the great Jedi Master, begins unsure - " ...

  4. python 类中定义类_Python中的动态类定义

    python 类中定义类 Here's a neat Python trick you might just find useful one day. Let's look at how you ca ...

  5. Log4j使用技巧——让子类使用父类中定义的Logger

    关于Log4j,是一个很庞大的话题,在这里,我不能对其特点和使用方法进行一一描述,只想记录自己在使用Log4j开发项目的过程中遇到的一些问题和自己的解决方案. 在项目中,有时候会遇到这么一种情况,我们 ...

  6. Vue 中定义方法页面上使用

    vue中定义方法的格式 为什么要这样定义 最近在学习前段,特别是HBuildX 我看里面很多方式都是这样使用,所以想强加练习 如何引用 当然我们的editArticle也可以直接放到js中,如下: 都 ...

  7. 在同一个文件中定义多个命名空间

    (PHP 5 >= 5.3.0, PHP 7) 也可以在同一个文件中定义多个命名空间.在同一个文件中定义多个命名空间有两种语法形式. Example #1 定义多个命名空间,简单组合语法 < ...

  8. 在python中定义类时、运算符重载_自定义 Python 类中的运算符和函数重载(上)...

    如果你对 Python 中的str对象使用过 + 或 * 运算符,你一定注意到了它的操作与 int 或 float 类型的区别: 你可能想知道同一内置运算符或函数如何对不同类对象进行不同操作的.这分别 ...

  9. 编写一个头文件,头文件中定义一个宏cube(x)用于求一个数的平方

    <程序设计基础实训指导教程-c语言> ISBN 978-7-03-032846-5 p145 7.1.2 上级实训内容 [实现内容17]编写一个头文件,头文件中定义一个宏cube(x)用于 ...

最新文章

  1. autoware使用激光雷达进行目标检测(五)
  2. Linux下修改mysql默认最大连接数,查看当前设置的最大连接数
  3. 利用jquery的imgAreaSelect插件实现图片裁剪示例
  4. 用友BIP助力大型企业构建“敏态+稳态”的数智企业摩天
  5. python PyQt5 QHBoxLayout 水平布局管理
  6. stringstream用法总结
  7. 从零开始学习docker(四)host
  8. 十四种Java开发工具点评
  9. 一些Xcode快捷键,给新手
  10. 【ZZ】大数据架构师基础:hadoop家族,Cloudera系列产品介绍
  11. C/C++函数学习(6)容器分类
  12. consul docker register
  13. Gamvas Web 0.8.4 发布,JavaScript 游戏引擎
  14. 快进来,详解MySQL游标
  15. 【FFmpeg】srs引入ffmpeg转码
  16. RTOS中的任务句柄到底是什么意思?
  17. 10 个超棒的 jQuery 视频插件
  18. Ps 2021教程,如何更换证件照背景?
  19. 微信公众号发送完红包后查看领取状态 源码
  20. Intel Realsense D435iL515 驱动安装

热门文章

  1. vue 生命周期_深入理解Vue实例生命周期
  2. oracle 空间数据处理,Oracle数据库空间数据的处理
  3. android+5.0+小米手环,小米手环5和荣耀手环6哪个好-参数对比
  4. mysql表损坏监控_监控mysql启动情况并检测表错误修复
  5. oracle 怎么读取模板,获取、部署和管理Oracle VM模板
  6. scala 主构造函数_Scala-构造函数
  7. (8)nginx:反向代理和负载均衡
  8. python字符串中最长的连续升序子串_Leetcode刷题练Python无重复字符的最长子串
  9. mysql_connect报告“No such file or directory“错误的解决方法
  10. R语言进阶 | 变量赋值背后的机制与R语言内存优化