C 语言 宏的技巧 结合回调函数

先来看一坨代码

#include <stdio.h>
#include <string.h>

//一些与最后打印 结果相关的宏
#define NUMFLAG ( ( (numsub) > (numdiv) ? (numsub) : (numdiv) ) > (numrem) ? ( (numsub) > (numdiv) ? (numsub) : (numdiv)) : (numrem) )
#define _FLAG_1 " - "
#define _FLAG_2 " / "
#define _FLAG_3 " % "



typedef int (*type_oprea)(int, int); //自定义 函数指针类型为 int (*)(int, int)


int numsub = 0, numdiv = 0, numrem = 0; //记录标志位
int m = 0, n =0;                        //记录数据位
char arrflag[20] = {0};                 //用来存放打印数据的数组
//与最后打印结果相关的函数 用来控制 arrflag数组 里面 存放的字符
void printflag(int a)
{
    if( a == 1) strcpy(arrflag, _FLAG_1);
    if( a == 2) strcpy(arrflag, _FLAG_2);
    if( a == 3) strcpy(arrflag, _FLAG_3);
}
//运算的函数
int sub(int a,int b)
{
    numsub = 1;//记录标志位 目的是判断 main函数 调用了哪个函数进行的运算
    m = a;     //记录 main函数里面 调用函数的形参
    n = b;     //为最后的打印 做提前记录

    return a - b;
}

int div(int a, int b)
{
    numdiv = 2;
    m = a;     
    n = b;

    return a / b;
}

int rem(int a,int b)
{
    numrem = 3;
    m = a;     
    n = b;

    return a % b;
}

//回调函数
///@type_oprea: 类型: int (*)(int, int)
///@type_parr: int (*)(int, int) 类型 的 变量
int func(type_oprea  type_parr, int a, int b)
{
   return type_parr(a,b);
}

int main(int argc, char const *argv[])
{
    //定义 函数指针 type_oprea类型的变量
    type_oprea psub = sub;
    type_oprea pdiv = div;
    type_oprea prem = rem;
    //定义一个 存放 type_oprea指针类型 的 指针数组 并 初始化赋值为 三个 运算函数的地址
    type_oprea Parr[3] = {psub,pdiv,prem};
    
    int ret = func(Parr[2],15,4);           //调用函数 传入参数 

    
    printflag(NUMFLAG);                    //掉用打印函数 判断回调的是哪个函数,作记录

    printf("%d%s%d = %d\n",m,arrflag,n,ret);//这是最后的打印
 
    return 0;
}

可以看出我在干什么吗?

答:你写的依托答辩,谁知道你代码在写啥!

带参宏

带参宏意味着宏定义可以携带“参数”,从形式上看跟函数很像,例如:

#define MAX(a, b)   a>b ? a : b
#define MIN(a, b)   a<b ? a : b
// 多个变量要用{}
#define A(a,b,c) ({a=1;b+=1;c=a+b;})

以上的MAX(a,b) 和 MIN(a,b) 都是带参宏,不管是否带参,宏都遵循最初的规则,即宏是一段待替换的文本,例如在以下代码中,宏在预处理阶段都将被替换掉:

int main()
{
    int x = 100, y = 200;
    printf("最大值:%d\n", MAX(x, y));
    printf("最小值:%d\n", MIN(x, y));
    // 以上代码等价于:
    // printf("最大值:%d\n", x>y ? x : y);
    // printf("最小值:%d\n", x<y ? x : y);
}
  • 带参宏的特点:

    1. 直接文本替换,不做任何语法判断,更不做任何中间运算。

    2. 宏在编译的第一个阶段就被替换掉,运行中不存在宏。

    3. 宏将在所有出现它的地方展开,这一方面浪费了内存空间,另一方面有节约了切换时间。

  • typedef与宏区别

    #include <stdio.h>
    ​
    // 宏是预编译的时候进行替换,无消耗编译时间
    // 宏是可以修改任意数据的别名
    // 一般数据该别名用宏
    #define int_t int
    #define PI 3.14
    ​
    // typedef : 编译的时候替换,消耗编译时间
    // typedef 只能用于关键字改别名
    // 一般数据类型改别名用typedef
    typedef int int32_t;
    //typedef 3.14 pi;
    ​
    int main(int argc, char const *argv[])
    {
        int32_t a = 10;
        int_t b = 20;
    ​
        return 0;
    }
    ​

无参宏

无参宏意味着使用宏的时候,无需指定任何参数,比如:

#define PI          3.14
#define SCREEN_SIZE 800*480*4 
int main()
{
    // 在代码中,可以随时使用以上无参宏,来替代其所代表的表达式:
    printf("圆周率: %f\n", PI); 
    mmap(NULL, SCREEN_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, ...);
}

注意到,上述代码中,除了有自定义的宏,还有系统预定义的宏:

// 自定义宏:
#define PI          3.14
#define SCREEN_SIZE 800*480*4 
​
// 系统预定义宏
#define NULL ((void *)0)
#define PROT_READ   0x1 /* Page can be read.  */
#define PROT_WRITE  0x2 /* Page can be written.  */
#define MAP_SHARED  0x01    /* Share changes.  */

宏的最基本特征是进行直接文本替换,以上代码被替换之后的结果是:

int main()
{
    printf("圆周率: %f\n", 3.14); 
    mmap(((void *)0), 800*480*4, 0x1|0x2, 0x01, ...);
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值