C语言还有不定参数
2015-12-28 11:01
399 查看
http://kmplayer.iteye.com/blog/842715
1,最近刚刚知道C语言还有不定参数这么个东东。
2,解决方法:
三个宏的使用va_arg()、va_start()和va_end()
上述的宏原型如下所示:
C代码
type va_arg(va_list argptr, type);
void va_end(va_list argptr);
void va_start(va_list argptr, last_parm);
它们都包含在头文件<stdarg.h>中。
在VC++6.0中,这几个宏的定义:
C代码
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1)) //类型n的大小
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //ap指向第一个不定参数地址
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址 返回当前ap指向的值,并且增加ap
#define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效
总结:读取可变参数的过程其实就是堆栈中,使用指针,遍历堆栈段中的参数列表,从低地址到高地址一个一个地把参数内容读出来的过程.
3,不定参数函数有个限制,就是不定参数的列表必须在整个函数的参数列表的最后。
我们不可以定义如下的函数:
void func(int a, ……, int c)
所有类型固定的参数都必须出现在参数列表的开始。
在设计具有不定参数列表的函数的时候,我们有两种方法来确定到底多少参数会被传递进来。
方法1是在类型固定的参数中指明后面有多少个参数以及他们的类型。printf就是采用的这种方法,它的format参数指明后面每个参数的类型。
方法2是指定一个结束参数。这种情况一般是不定参数拥有同样的类型,我们可以指定一个特定的值来表示参数列表结束。
4,实例代码:
C代码
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
int sumi(int c, ...)
{
va_list argptr;
va_start(argptr, c); //初始化变元指针
int sum = c;
c = va_arg(argptr, int); //作为下一个参数类型的参数类型,返回不定参数
//c保存第一个不定参数
printf("%d\n", c);
while(0 != c) //末尾特定字符指示结束
{
sum = sum + c;
c = va_arg(argptr, int);
}
va_end(argptr);
return sum;
}
double sum_series(int num, ...)
{
double sum = 0.0, t;
va_list argptr;
va_start(argptr, num);//初始化变元指针
while (num--)
{
t = va_arg(argptr, double);
sum = sum + t;
}
va_end(argptr);
return sum;
}
int main()
{
int i = sumi(1,2,3,4,5,6,7,8,9,0);
printf("%d\n", i);
double d = sum_series(4, 1/3.0, 1/4.0, 1/5.0, 1/6.0);
printf("%f\n", d);
return 0;
}
1,最近刚刚知道C语言还有不定参数这么个东东。
2,解决方法:
三个宏的使用va_arg()、va_start()和va_end()
上述的宏原型如下所示:
C代码
type va_arg(va_list argptr, type);
void va_end(va_list argptr);
void va_start(va_list argptr, last_parm);
它们都包含在头文件<stdarg.h>中。
在VC++6.0中,这几个宏的定义:
C代码
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1)) //类型n的大小
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //ap指向第一个不定参数地址
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址 返回当前ap指向的值,并且增加ap
#define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效
总结:读取可变参数的过程其实就是堆栈中,使用指针,遍历堆栈段中的参数列表,从低地址到高地址一个一个地把参数内容读出来的过程.
3,不定参数函数有个限制,就是不定参数的列表必须在整个函数的参数列表的最后。
我们不可以定义如下的函数:
void func(int a, ……, int c)
所有类型固定的参数都必须出现在参数列表的开始。
在设计具有不定参数列表的函数的时候,我们有两种方法来确定到底多少参数会被传递进来。
方法1是在类型固定的参数中指明后面有多少个参数以及他们的类型。printf就是采用的这种方法,它的format参数指明后面每个参数的类型。
方法2是指定一个结束参数。这种情况一般是不定参数拥有同样的类型,我们可以指定一个特定的值来表示参数列表结束。
4,实例代码:
C代码
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
int sumi(int c, ...)
{
va_list argptr;
va_start(argptr, c); //初始化变元指针
int sum = c;
c = va_arg(argptr, int); //作为下一个参数类型的参数类型,返回不定参数
//c保存第一个不定参数
printf("%d\n", c);
while(0 != c) //末尾特定字符指示结束
{
sum = sum + c;
c = va_arg(argptr, int);
}
va_end(argptr);
return sum;
}
double sum_series(int num, ...)
{
double sum = 0.0, t;
va_list argptr;
va_start(argptr, num);//初始化变元指针
while (num--)
{
t = va_arg(argptr, double);
sum = sum + t;
}
va_end(argptr);
return sum;
}
int main()
{
int i = sumi(1,2,3,4,5,6,7,8,9,0);
printf("%d\n", i);
double d = sum_series(4, 1/3.0, 1/4.0, 1/5.0, 1/6.0);
printf("%f\n", d);
return 0;
}
相关文章推荐
- C\C++各路高手以及操作系统专家请进来杀死这个进程
- 课程设计——c++中读取txt文件
- C++ STL priority_queue
- C语言---类型转换
- GC基本算法及C++GC机制
- vs2008中C++项目编译过程中越来越慢
- const——c与c++不同
- C语言字符串操作总结大全
- 【C++】动态开辟二维数组
- 【C++】斐波那契数列前N项的和递归与非递归算法
- C/C++——C和C++怎样分配和释放内存,区别是什么?
- 图的最短路径问题————树上奶牛(tree.cpp)
- c++标准库 及 命名空间std
- C语言创始人
- c++异常处理
- 【c语言】模拟库函数strstr
- c++变量的存储区域
- C语言数组内存初始化
- 《C语言及程序设计》第22讲实践项目
- C++ iterator 前++ 后++ 效率区别