第34节 可变参数分析与宏分析
-------------------------------------资源来源于网络,仅供自学使用,如有侵权,联系我必删.
第一:
? 如何编写一个可以计算n 个数平均值的函数
#include <stdio.h>
float func(int array[], int size)
{
int i = 0;
float avr = 0;
for(i=0; i<size; i++)
{
avr += array[i];
}
return avr / size;
}
int main()
{
//将n个数放到一个数组里面,然后再求平均值
int array[] = {1, 2, 3, 4, 5};
printf("%f\n", func(array, 5));
return 0;
}
第二
可变参数
? C 语言中可以定义参数可变的函数
? 参数可变函数的实现依赖于stdarg.h 头文件
? va_list 变量与va_start, va_end 和va_arg 配合使用能够访问参数值
可变参数的定义与使用
#include <stdio.h>
#include <stdarg.h>
float average(int n, ...)//n表示有多少个参数 ...表示可变参数
{
va_list args;//可变参数列表,依赖于stdarg.h 头文件
int i = 0;
float sum = 0;
va_start(args, n);//开始取得不定参数
for(i=0; i<n; i++)
{
sum += va_arg(args, int);
}
va_end(args);//结束取值
return sum / n;
}
int main()
{
printf("%f\n", average(5, 1, 2, 3, 4, 5));
printf("%f\n", average(4, 1, 2, 3, 4));
return 0;
}
第三:
可变参数的限制
? 可变参数必须从头到尾按照顺序逐个访问
? 参数列表中至少要存在一个确定的命名参数
? 可变参数宏无法判断实际存在的参数的数量
? 可变参数宏无法判断参数的实际类型
警告 :
va_arg 中如果指定了错误的类型 , 那么结果是不可预测的 .
小结
? 可变参数是C 语言提供的一种函数设计技巧
? 可变参数的函数提供了一种更方便的函数调用方式
? 可变参数必须顺序的访问
? 无法直接访问可变参数列表中间的参数值
-------------------------------------------------------------------------------------------------------------------
第四:
函数 VS 宏
#include <stdio.h>
#define RESET(p, len) while( len > 0) ((char*)p)[--len] = 0
void reset(void* p, int len)
{
while( len > 0 )
{
((char*)p)[--len] = 0;
}
}
int main()
{
int array[] = {1, 2, 3, 4, 5};
int len = sizeof(array);
int i;
for(i=0;i<5;i++)
{
printf("%d\n", array[i]);
}
reset(array, len);
//RESET(array, len);
for(i=0;i<5;i++)
{
printf("%d\n", array[i]);
}
return 0;
}
? 宏是由预处理直接替换展开的 , 编译器不知道宏的存在
? 函数是由编译器直接编译的实体 , 调用行为由编译器决定
? 多次使用宏会导致程序代码量增加
? 函数是跳转执行的 , 因此代码量不会增加
? 宏的效率比函数要高 , 因为是直接展开 , 无调用开销
? 函数调用时会创建活动记录 ,效率不如宏
第五:
宏的优点和缺点
? 宏的效率比函数稍高 , 但是其副作用巨大 , 容易出错
#include <stdio.h>
#define ADD(a, b) a + b
#define MUL(a, b) a * b
#define _MIN_(a, b) ((a) < (b) ? (a) : (b))
int main()
{
int i = 1;
int j = 10;
printf("%d\n", MUL(ADD(1, 2), ADD(3, 4)));//1 + 2 * 3 + 4
printf("%d\n", _MIN_(i++, j)); //((i++) < (j) ? (i++) : (j))) 顺序点在逗号表达式,i++计算出来是2结束
return 0;
}
? 函数存在实参到形参的传递 , 因此无任何副作用,但是函数需要建立活动对象 ,效率受影响
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int mul(int a, int b)
{
return a * b;
}
int _min_(int a, int b)
{
return a < b ? a : b;
}
int main()
{
int i = 1;
int j = 10;
printf("%d\n", mul(add(1, 2), add(3, 4)));
printf("%d\n", _min_(i++, j));
return 0;
}
? 宏参数可以是任何C 语言实体
宏编写的_MIN_ 参数类型可以是int, float 等等
宏的参数可以是类型名
#define MALLOC(type,n) (type*)malloc(n * sizeof(type))
int* p = MALLOC(int,5)
#include <stdio.h>
#include <malloc.h>
//参数类型可变!!!!
#define MALLOC(type, n) (type*)malloc(n * sizeof(type))
int main()
{
int* p = MALLOC(int, 5);
int i = 0;
for(i=0; i<5; i++)
{
p[i] = i + 1;
printf("%d\n", p[i]);
}
free(p);
return 0;
}
小结
? 宏和函数并不是竞争对手
? 宏能够接受任何类型的参数 , 效率高 , 易出错
? 函数的参数必须是固定类型 , 效率稍低 , 不易出错
? 宏可以实现函数不能实现的功能