第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;
}

第34节 可变参数分析与宏分析

第三:

可变参数的限制

?  可变参数必须从头到尾按照顺序逐个访问
?  参数列表中至少要存在一个确定的命名参数
?  可变参数宏无法判断实际存在的参数的数量
?  可变参数宏无法判断参数的实际类型

警告 :
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;
}

第34节 可变参数分析与宏分析

第34节 可变参数分析与宏分析

?  宏是由预处理直接替换展开的 , 编译器不知道宏的存在
?  函数是由编译器直接编译的实体 , 调用行为由编译器决定
?  多次使用宏会导致程序代码量增加
?  函数是跳转执行的 , 因此代码量不会增加
?  宏的效率比函数要高 , 因为是直接展开 , 无调用开销
?  函数调用时会创建活动记录 ,效率不如宏

 

第五:

宏的优点和缺点

? 宏的效率比函数稍高 , 但是其副作用巨大 , 容易出错

#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;
}

第34节 可变参数分析与宏分析

? 函数存在实参到形参的传递 , 因此无任何副作用,但是函数需要建立活动对象 ,效率受影响

#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;
}

第34节 可变参数分析与宏分析

 

?  宏参数可以是任何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;
}

第34节 可变参数分析与宏分析

小结

?  宏和函数并不是竞争对手
?  宏能够接受任何类型的参数 , 效率高 , 易出错
?  函数的参数必须是固定类型 , 效率稍低 , 不易出错
?  宏可以实现函数不能实现的功能