宏分析(李逵和李鬼)

函数(C语言的核心)

专题六:函数(C语言的核心)。包括以下章节:

  • 认清函数的真面目
  • 可变参数列表
  • 李逵和李鬼
  • 函数调用行为
  • 函数递归详解
  • 函数设计技巧

李逵 VS 李鬼

3-1.c

#include <stdio.h>

#define RESET(p, len) while( len > 0) ((char*)p)[--len] = 0

void reset(void* p, int len)
{
    while( len > 0 )
    {
        //p[--len] ==> *(p+(--len))
        //p指向的空间每个字节都设为0
        ((char*)p)[--len] = 0;
    }
}

int main()
{
    int array[] = {1, 2, 3, 4, 5};
    int len = sizeof(array);
    int i = 0;

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

函数 VS 宏

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

宏的优点和缺点

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

3-2.c

#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", 1+2*3+4),不是我们想要的结果
    printf("%d\n", MUL(ADD(1, 2), ADD(3, 4)));
    //直接展开:printf("%d\n", ((i++) < (j) ? (i++) : (j)))
    //((i++) < (j) ? (i++) : (j)) "?:"是顺序点,"?"之前计算一次i=2,所以printf("%d\n", i++)打印是2
    printf("%d\n", _MIN_(i++, j));

    return 0;
}

结果:
这里写图片描述

函数优点和缺点

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

3-3.c

#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语言实体

  1. 宏编写的MIN参数类型可以是int, float等等
  2. 宏的参数可以是类型名

3-4.c

#include <stdio.h>
#include <malloc.h>

#define MALLOC(type, n) (type*)malloc(n * sizeof(type))

int main()
{   //而函数不可能传递int(类型名)参数
    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;
}

小结

  1. 宏和函数并不是竞争对手
  2. 宏能够接受任何类型的参数,效率高,易出错
  3. 函数的参数必须是固定类型,效率稍低,不易出错
  4. 宏可以实现函数不能实现的功能
├─res │ │ filemd5List.json │ │ │ ├─bank_res │ │ bank_title.png │ │ bt_getout_0.png │ │ bt_getout_1.png │ │ bt_open_0.png │ │ bt_open_1.png │ │ edit_frame.png │ │ im_arrow.png │ │ im_gold.png │ │ im_money.png │ │ │ ├─gameClear │ │ bt_quit_game_0.png │ │ bt_quit_game_1.png │ │ bt_return_game_0.png │ │ bt_return_game_1.png │ │ clearBox.png │ │ fishCatchNum.png │ │ fishMultipleNum.png │ │ multiple.png │ │ scoreNum.png │ │ │ ├─game_res │ │ Bank.csb │ │ blue.plist │ │ blue.png │ │ bomb.plist │ │ bomb.png │ │ boom_darts.plist │ │ boom_darts.png │ │ bt_bank_0.png │ │ bt_bank_1.png │ │ bt_blue_0.png │ │ bt_blue_1.png │ │ bt_blue_2.png │ │ bt_check_no.png │ │ bt_check_yes.png │ │ bt_clearing_0.png │ │ bt_clearing_1.png │ │ bt_fishtype_0.png │ │ bt_fishtype_1.png │ │ bt_green_0.png │ │ bt_green_1.png │ │ bt_green_2.png │ │ bt_help_0.png │ │ bt_help_1.png │ │ bt_menu_0.png │ │ bt_menu_1.png │ │ bt_mute_0.png │ │ bt_mute_1.png │ │ bt_mute_2.png │ │ bt_operation_0.png │ │ bt_operation_1.png │ │ bt_purple_0.png │ │ bt_purple_1.png │ │ bt_purple_2.png │ │ bt_quit_game_0.png │ │ bt_quit_game_1.png │ │ bt_red_0.png │ │ bt_red_1.png │ │ bt_red_2.png │ │ bt_return_game_0.png │ │ bt_return_game_1.png │ │ bt_send_0.png │ │ bt_send_1.png │ │ bt_setting_0.png │ │ bt_setting_1.png │ │ bt_supply_0.png │ │ bt_supply_1.png │ │ bt_yellow_0.png │ │ bt_yellow_1.png │ │ bt_yellow_2.png │ │ bullet.plist │ │ bullet.png │ │ bullet_bodies.plist │ │ bullet_guns_coins.plist │ │ bullet_guns_coins.png │ │ Cannon.csb │ │ chatBox.png │ │ clew_b
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值