C语言细节 - 可变参数列表

头文件引用

为了使用可变参数列表,你需要添加标准库中的 “stdarg.h”

头文件中定义的一个类型和三个宏
va_list
typedef char *va_list;	

va : variable argument


va_start
#define va_start(AP, LASTARG)	(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))));

功能:使ap指向函数中可变参数的首地址:
__va_rounded_size 是内存对齐宏详见:C语言内存对齐详解3


va_arg
#define va_arg(AP, TYPE) \
   (AP += __va_rounded_size (TYPE),	\
   *((TYPE *) (AP - __va_rounded_size (TYPE))))

功能:1.返回可变参数的当前参数;2.将指针指向下一个参数;所有可变参数类型都设定为TYPE
注:函数无法判断检索到的参数是否是可变参数列的最后一个参数


va_end
#define va_end(ap)      ( ap = (va_list)0 )

注:va_end常与va_start成对使用

使用示例:
#include <stdio.h>
#include <stdarg.h>

void var_test(char *format, ...)
{
    va_list list;
    va_start(list,format);

    char *p;

    while( (p=va_arg(list, char *)) != NULL )
         printf("%s ",p);

     va_end(list);
}

int main()
{
    var_test("","this","is","a","test",NULL);

    return 0;
}

参考文献:C语言中可变参数函数实现原理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
目 录 译者序 前言 第1章 对象的演化 1 1.1 基本概念 1 1.1.1 对象:特性+行为 1 1.1.2 继承:类型关系 1 1.1.3 多态性 2 1.1.4 操作概念:OOP程序像什么 3 1.2 为什么C++会成功 3 1.2.1 较好的C 3 1.2.2 采用渐进的学习方式 4 1.2.3 运行效率 4 1.2.4 系统更容易表达和理解 4 1.2.5 “库”使你事半功倍 4 1.2.6 错误处理 5 1.2.7 大程序设计 5 1.3 方法学介绍 5 1.3.1 复杂性 5 1.3.2 内部原则 6 1.3.3 外部原则 7 1.3.4 对象设计的五个阶段 9 1.3.5 方法承诺什么 10 1.3.6 方法应当提供什么 10 1.4 起草:最小的方法 12 1.4.1 前提 13 1.4.2 高概念 14 1.4.3 论述(treatment) 14 1.4.4 结构化 14 1.4.5 开发 16 1.4.6 重写 17 1.4.7 逻辑 17 1.5 其他方法 17 1.5.1 Booch 18 1.5.2 责任驱动的设计(RDD) 19 1.5.3 对象建模技术(OMT) 19 1.6 为向OOP转变而采取的策略 19 1.6.1 逐步进入OOP 19 1.6.2 管理障碍 20 1.7 小结 21 第2章 数据抽象 22 2.1 声明与定义 22 2.2 一个袖珍C库 23 2.3 放在一起:项目创建工具 29 2.4 什么是非正常 29 2.5 基本对象 30 2.6 什么是对象 34 2.7 抽象数据类型 35 2.8 对象细节 35 2.9 头文件形式 36 2.10 嵌套结构 37 2.11 小结 41 2.12 练习 41 第3章 隐藏实现 42 3.1 设置限制 42 3.2 C++的存取控制 42 3.3 友元 44 3.3.1 嵌套友元 45 3.3.2 它是纯的吗 48 3.4 对象布局 48 3.5 类 48 3.5.1 用存取控制来修改stash 50 3.5.2 用存取控制来修改stack 51 3.6 句柄类(handle classes) 51 3.6.1 可见的实现部分 51 3.6.2 减少重复编译 52 3.7 小结 54 3.8 练习 54 第4章 初始化与清除 55 4.1 用构造函数确保初始化 55 4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省构造函数 67 4.8 小结 68 4.9 练习 68 第5章 函数重载与缺省参数 69 5.1 范围分解 69 5.1.1 用返回值重载 70 5.1.2 安全类型连接 70 5.2 重载的例子 71 5.3 缺省参数 74 5.4 小结 81 5.5 练习 82 第6章 输入输出流介绍 83 6.1 为什么要用输入输出流 83 6.2 解决输入输出流问题 86 6.2.1 预先了解操作符重载 86 6.2.2 插入符与提取符 87 6.2.3 通常用法 88 6.2.4 面向行的输入 90 6.3 文件输入输出流 91 6.4 输入输出流缓冲 93 6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子 108 6.10 输入输出流实例 111 6.10.1 代码生成 111 6.10.2 一个简单的数据记录 117 6.11 小结 123 6.12 练习 123 第7章 常量 124 7.1 值替代 124 7.1.1 头文件里的const 124 7.1.2 const的安全性 125 7.1.3 集合 126 7.1.4 与C语言的区别 126 7.2 指针 127 7.2.1 指向const的指针 127 7.2.2 const指针 127 7.2.3 赋值和类型检查 128 7.3 函数参数和返回值 128 7.3.1 传递const值 128 7.3.2 返回const值 129 7.3.3 传递和返回地址 131 7.4 类 133 7.4.1 类里的const和enum 133 7.4.2 编译期间类里的常量 134 7.4.3 const对象和成员函数 136 7.4.4 只读存储能力 139 7.5 可变的(volatile) 140 7.6 小结 141 7.7 练习 141 第8章 内联函数 142 8.1 预处理器的缺陷 142 8.2 内联函数 144 8.2.1 类内部的内联函数 145 8.2.2 存取函数 146 8.3 内联函数和编译器 150 8.3.1 局限性 150 8.3.2 赋值顺序 150 8.3.3 在构造函数和析构函数里隐藏行为 151 8.4 减少混乱 152 8.5 预处理器的特点 153 8.6 改进的错误检查 154 8.7 小结 155 8.8 练习 155 第9章 命名控制 157 9.1 来自C语言中的静态成员 157 9.1.1 函数内部的静态变量 157 9.1.2 控制连接 160 9.1.3 其他的存储类型指定符 161 9.2 名字空间 161 9.2.1 产生一个名字空间 162 9.2.2 使用名字空间 163 9.3 C++中的静态成员 166 9.3.1 定义静态数据成员的存储 166 9.3.2 嵌套类和局部类 168 9.3.3 静态成员函数 169 9.4 静态初始化的依赖因素 171 9.5 转换连接指定 174 9.6 小结 174 9.7 练习 174 第10章 引用和拷贝构造函数 176 10.1 C++中的指针 176 10.2 C++中的引用 176 10.2.1 函数中的引用 177 10.2.2 参数传递准则 178 10.3 拷贝构造函数 179 10.3.1 传值方式传递和返回 179 10.3.2 拷贝构造函数 182 10.3.3 缺省拷贝构造函数 187 10.3.4 拷贝构造函数方法的选择 188 10.4 指向成员的指针
C++编程思想6-10 目 录 译者序 前言 第1章 对象的演化 1 1.1 基本概念 1 1.1.1 对象:特性+行为 1 1.1.2 继承:类型关系 1 1.1.3 多态性 2 1.1.4 操作概念:OOP程序像什么 3 1.2 为什么C++会成功 3 1.2.1 较好的C 3 1.2.2 采用渐进的学习方式 4 1.2.3 运行效率 4 1.2.4 系统更容易表达和理解 4 1.2.5 “库”使你事半功倍 4 1.2.6 错误处理 5 1.2.7 大程序设计 5 1.3 方法学介绍 5 1.3.1 复杂性 5 1.3.2 内部原则 6 1.3.3 外部原则 7 1.3.4 对象设计的五个阶段 9 1.3.5 方法承诺什么 10 1.3.6 方法应当提供什么 10 1.4 起草:最小的方法 12 1.4.1 前提 13 1.4.2 高概念 14 1.4.3 论述(treatment) 14 1.4.4 结构化 14 1.4.5 开发 16 1.4.6 重写 17 1.4.7 逻辑 17 1.5 其他方法 17 1.5.1 Booch 18 1.5.2 责任驱动的设计(RDD) 19 1.5.3 对象建模技术(OMT) 19 1.6 为向OOP转变而采取的策略 19 1.6.1 逐步进入OOP 19 1.6.2 管理障碍 20 1.7 小结 21 第2章 数据抽象 22 2.1 声明与定义 22 2.2 一个袖珍C库 23 2.3 放在一起:项目创建工具 29 2.4 什么是非正常 29 2.5 基本对象 30 2.6 什么是对象 34 2.7 抽象数据类型 35 2.8 对象细节 35 2.9 头文件形式 36 2.10 嵌套结构 37 2.11 小结 41 2.12 练习 41 第3章 隐藏实现 42 3.1 设置限制 42 3.2 C++的存取控制 42 3.3 友元 44 3.3.1 嵌套友元 45 3.3.2 它是纯的吗 48 3.4 对象布局 48 3.5 类 48 3.5.1 用存取控制来修改stash 50 3.5.2 用存取控制来修改stack 51 3.6 句柄类(handle classes) 51 3.6.1 可见的实现部分 51 3.6.2 减少重复编译 52 3.7 小结 54 3.8 练习 54 第4章 初始化与清除 55 4.1 用构造函数确保初始化 55 4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省构造函数 67 4.8 小结 68 4.9 练习 68 第5章 函数重载与缺省参数 69 5.1 范围分解 69 5.1.1 用返回值重载 70 5.1.2 安全类型连接 70 5.2 重载的例子 71 5.3 缺省参数 74 5.4 小结 81 5.5 练习 82 第6章 输入输出流介绍 83 6.1 为什么要用输入输出流 83 6.2 解决输入输出流问题 86 6.2.1 预先了解操作符重载 86 6.2.2 插入符与提取符 87 6.2.3 通常用法 88 6.2.4 面向行的输入 90 6.3 文件输入输出流 91 6.4 输入输出流缓冲 93 6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子 108 6.10 输入输出流实例 111 6.10.1 代码生成 111 6.10.2 一个简单的数据记录 117 6.11 小结 123 6.12 练习 123 第7章 常量 124 7.1 值替代 124 7.1.1 头文件里的const 124 7.1.2 const的安全性 125 7.1.3 集合 126 7.1.4 与C语言的区别 126 7.2 指针 127 7.2.1 指向const的指针 127 7.2.2 const指针 127 7.2.3 赋值和类型检查 128 7.3 函数参数和返回值 128 7.3.1 传递const值 128 7.3.2 返回const值 129 7.3.3 传递和返回地址 131 7.4 类 133 7.4.1 类里的const和enum 133 7.4.2 编译期间类里的常量 134 7.4.3 const对象和成员函数 136 7.4.4 只读存储能力 139 7.5 可变的(volatile) 140 7.6 小结 141 7.7 练习 141 第8章 内联函数 142 8.1 预处理器的缺陷 142 8.2 内联函数 144 8.2.1 类内部的内联函数 145 8.2.2 存取函数 146 8.3 内联函数和编译器 150 8.3.1 局限性 150 8.3.2 赋值顺序 150 8.3.3 在构造函数和析构函数里隐藏行为 151 8.4 减少混乱 152 8.5 预处理器的特点 153 8.6 改进的错误检查 154 8.7 小结 155 8.8 练习 155 第9章 命名控制 157 9.1 来自C语言中的静态成员 157 9.1.1 函数内部的静态变量 157 9.1.2 控制连接 160 9.1.3 其他的存储类型指定符 161 9.2 名字空间 161 9.2.1 产生一个名字空间 162 9.2.2 使用名字空间 163 9.3 C++中的静态成员 166 9.3.1 定义静态数据成员的存储 166 9.3.2 嵌套类和局部类 168 9.3.3 静态成员函数 169 9.4 静态初始化的依赖因素 171 9.5 转换连接指定 174 9.6 小结 174 9.7 练习 174 第10章 引用和拷贝构造函数 176 10.1 C++中的指针 176 10.2 C++中的引用 176 10.2.1 函数中的引用 177 10.2.2 参数传递准则 178 10.3 拷贝构造函数 179 10.3.1 传值方式传递和返回 179 10.3.2 拷贝构造函数 182 10.3.3 缺省拷贝构造函数 187 10.3.4 拷贝构造函数方法的选择 188 10.4 指向成员的指针
译者序 作者简介 技术审校人员简介 第1章 前言 1.1 本书的内容 1.2 本书的组织方式 1.3 致谢 第1部分 Objective-C语言 第2章 Objective-C程序设计 2.1 编译并运行程序 2.1.1 使用Xcode 2.1.2 使用Terminal 2.2 解释第一个程序 2.3 显示变量的值 2.4 小结 2.5 练习 第3章 类、对象和方法 3.1 到底什么是对象 3.2 实例和方法 3.3 用于处理分数的Objective-C类 3.4 @interface部分 3.4.1 选择名称 3.4.2 实例变量 3.4.3 类和实例方法 3.5 @implementation部分 3.6 Program部分 3.7 实例变量的访问以及数据封装 3.8 小结 3.9 练习 第4章 数据类型和表达式 4.1 数据类型和常量 4.1.1 int类型 4.1.2 float类型 4.1.3 double类型 4.1.4 char类型 4.1.5 限定词:long、long long、short、unsigned及signed 4.1.6 id类型 4.2 算术表达式 4.2.1 运算符的优先级 4.2.2 整数运算和一元负号运算符 4.2.3 模运算符 4.2.4 整型值和浮点值的相互转换 4.2.5 类型转换运算符 4.3 赋值运算符 4.4 计算器类 4.5 位运算符 4.5.1 按位与运算符 4.5.2 按位或运算符 4.5.3 按位异或运算符 4.5.4 一次求反运算符 4.5.5 向左移位运算符 4.5.6 向右移位运算符 4.6 类型:_Bool、_Complex和_Imaginary 4.7 练习 第5章 循环结构 5.1 for语句 5.1.1 键盘输入 5.1.2 嵌套的for循环 5.1.3 for循环的变形 5.2 while语句 5.3 do语句 5.4 break语句 5.5 continue语句 5.6 小结 5.7 练习 第6章 选择结构 6.1 if语句 6.1.1 if-else结构 6.1.2 复合条件测试 6.1.3 嵌套的if语句 6.1.4 else if结构 6.2 switch语句 6.3 Boolean变量 6.4 条件运算符 6.5 练习 第7章 类 7.1 分离接口和实现文件 7.2 合成存取器方法 7.3 使用点运算符访问属性 7.4 具有多个参数的方法 7.4.1 不带参数名的方法 7.4.2 关于分数的操作 7.5 局部变量 7.5.1 方法的参数 7.5.2 static关键字 7.6 self关键字 7.7 在方法中分配和返回对象 7.8 练习.. 第8章 继承 8.1 一切从根类开始 8.2 通过继承扩展—添加新方法 8.2.1 Point类和内存分配 8.2.2 @class指令 8.2.3 具有对象的类 8.3 重载方法 8.3.1 择哪个方法 8.3.2 重载dealloc方法和关键字super 8.4 通过继承扩展:添加新的实例变量 8.5 抽象类 8.6 练习 第9章 多态、动态类型和动态绑定 9.1 多态:相同的名称,不同的类 9.2 动态绑定和id类型 9.3 编译时和运行时检查 9.4 id数据类型与静态类型 9.5 有关类的问题 9.6 使用@try处理异常 9.7 练习 第10章 变量和数据类型 10.1 类的初始化 10.2 作用域回顾 10.2.1 控制实例变量作用域的指令 10.2.2 外部变量 10.2.3 静态变量 10.3 存储类说明符 10.3.1 auto 10.3.2 const 10.3.3 volatile 10.4 枚举数据类型 10.5 typedef语句 10.6 数据类型转换 10.6.1 转换规则 10.6.2 符号扩展 10.7 练习 第11章 分类和协议 11.1 分类 11.2 协议 11.3 合成对象 11.4 练习 第12章 预处理程序 12.1 #define语句 12.1.1 更高级的定义类型 12.1.2 #运算符 12.1.3 ##运算符 12.2 #import语句 12.3 条件编译 12.3.1 #ifdef、#endif、#else和#ifndef语句 12.3.2 #if和#elif预处理程序语句 12.3.3 #undef语句 12.4 练习 第13章 基本的C语言特性 13.1 数组 13.1.1 数组元素的初始化 13.1.2 字符数组 13.1.3 多维数组 13.2 函数 13.2.1 参数和局部变量 13.2.2 函数的返回结果 13.2.3 函数、方法和数组 13.3 结构 13.3.1 结构的初始化 13.3.2 结构数组 13.3.3 结构中的结构 13.3.4 关于结构的补充细节 13.3.5 不要忘记面向对象编程思想 13.4 指针 13.4.1 指针和结构 13.4.2 指针、方法和函数 13.4.3 指针和数组 13.4.4 指针运算 13.4.5 指针和内存地址 13.5 联合 13.6 它们不是对象 13.7 其他语言特性 13.7.1 Compound Literal 13.7.2 goto语句 13.7.3 空语句 13.7.4 逗号运算符 13.7.5 sizeof运算符 13.7.6 命令行参数 13.8 工作原理 事实#1:实例变量存储在结构中 事实#2:对象变量实际上是指针 事实#3:方法是函数,而消息表达式是 函数调用 事实#4:id类型是通用指针类型 13.9 练习 第二部分 Foundation框架 第14章 Foundation框架简介 第15章 数字、字符串和集合 15.1 数字对象 15.2 字符串对象 15.2.1 NSLog函数 15.2.2 可变对象与不可变对象 15.2.3 可变字符串 15.2.4 所有对象到哪里去了 15.3 数组对象 15.4 同步AddressCard方法 15.4.1 快速枚举 15.4.2 数组排序 15.5 词典对象 15.6 集合对象 15.7 练习 第16章 使用文件 16.1 管理文件和目录:NSFileManager 16.1.1 使用NSData类 16.1.2 使用目录 16.1.3 枚举目录中的内容 16.2 使用路径:NSPathUtilities.h 16.2.1 常用的路径处理方法 16.2.2 复制文件和使用NSProcessInfo类 16.3 基本的文件操作:NSFileHandle 16.4 练习 第17章 内存管理 17.1 自动释放池 17.2 引用计数 17.2.1 引用计数和字符串 17.2.2 引用计数与实例变量 17.3 自动释放池示例 17.4 内存管理规则摘要 17.5 垃圾回收 17.6 练习 第18章 复制对象 18.1 copy和mutableCopy方法 18.2 浅复制与深复制 18.3 实现协议 18.4 用赋值方法和取值方法复制对象 18.5 练习 第19章 归档 19.1 使用XML属性列表进行归档 19.2 使用NSKeyedArchiver归档 19.3 编码方法和解码方法 19.4 使用NSData创建自定义档案 19.5 使用归档程序复制对象 19.6 练习 第三部分 Cocoa和iPhone SDK 第20章 Cocoa简介 20.1 框架层 20.2 接触Cocoa 第21章 编写iPhone应用程序 21.1 iPhone SDK 21.2 第一个iPhone应用程序 21.2.1 创建新的iPhone应用程序项目 21.2.2 输入代码 21.2.3 设计界面 21.3 iPhone分数计算器 21.3.1 启动新的Fraction_Calculator项目 21.3.2 定义视图控制器 21.3.3 Fraction类 21.3.4 处理分数的Calculator类 21.3.5 设计UI 21.4 小结 21.5 练习 第四部分 附录 附录A 术语表 附录B Objective-C 2.0语言概览 附录C 地址簿源代码 附录D 资源

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

|清风|

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值