• 优雅的c语言宏定义比较大小


    写一个宏定义,返回两个数中较大的一个。相信绝大部分同学都能闭着眼睛写出来,但闭着眼睛写的真的对吗,怎么样写可以做到极致的优雅,适用几乎所有应用场景。

    幼儿园写法:

    #define MAX(a, b) a > b ? a : b

            但是有些不听话的小朋友在使用这个宏的时候可能会这样写:

    1. #include <stdio.h>
    2. #define MAX(a, b) a > b ? a : b
    3. int main (int argc, char *argv[])
    4. {
    5. printf("%d", MAX(4&4, 2&4));
    6. return 0;
    7. }

            运行结果:

    0

    这就出错了,这是由于运算符优先级导致了运行结果偏离预期,&的优先级小于<。

    小学写法:

    #define MAX(a, b) (a) > (b) ? (a) : (b)

    也有一些聪明的小学生,会写到:

    1. #include
    2. #define MAX(a, b) (a) > (b) ? (a) : (b)
    3. int main (int argc, char *argv[])
    4. {
    5. printf("%d\n", 1+MAX(3, 2));
    6. return 0;
    7. }

    运行结果是3!这也是因为运算符优先级引发的问题,+的优先级要大于>。

    初中写法:

    #define MAX(a, b) ((a) > (b) ? (a) : (b))

    这样写很好地规避了运算符优先级带来的问题,但它还不是完美的,请看:

    1. #include <stdio.h>
    2. #define MAX(a, b) ((a) > (b) ? (a) : (b))
    3. int main (int argc, char *argv[])
    4. {
    5. int a = 3, b=4;
    6. printf("%d\n", 1+MAX(a++, b++));
    7. return 0;
    8. }

    运行结果是6!这是因为在比较的过程中,变量自身发生了变化,虽然编程规范一般不允许这样传递参数,但到底有没有办法规避这些隐患呢。

    高中写法:

    1. #define MAX(a, b) ({ \
    2. int _a = a; \
    3. int _b = b; \
    4. _a > _b ? _a : _b; \
    5. })

    这个写法已经能规避很多问题了,但很明显的问题是,它只适用于int类型数据的比较。于是又有了

    本科写法:

    1. #define MAX(type, a, b) ({ \
    2. type _a = a; \
    3. type _b = b; \
    4. _a > _b ? _a : _b; \
    5. })

    这样就可以支持多种数据类型了。但是它要用到3个“参数”,我需要比较两个数的大小,为什么要我传递3个“参数”呢。

    硕士写法:

    1. #define MAX(a, b) ({ \
    2. typeof(a) _a = a; \
    3. typeof(b) _b = b; \
    4. (void)(&_a == &_b); \
    5. _a > _b ? _a : _b; \
    6. })

    typeof在gun c上是可以支持的,它可以自动获取参数类型。

    (void)(&_a == &_b);这条语句则可以用来提示传入参数类型不一致的警告。编译的时候就可以提示警告。

    到这里,比较大小的宏定义已经足够优雅了。也许你会觉得写个宏定义需要这么复杂吗,别急,不妨再看看《内联函数》

  • 相关阅读:
    Excel大量表格选择,快速定位表格
    用Java语言创建的Spring Boot项目中,如何传递数组呢??
    网络安全(黑客)自学
    AttitudeFactor.h/AttitudeFactor.cpp
    Mysql 索引原理和优化方式
    20221130今天的世界发生了什么
    SQL没有指定返回结果类型的映射
    Git使用
    Oracle Primavera Unifier组合管理器(Portfolio Manager)
    Vue+Electron打包桌面应用(从零到一完整教程)
  • 原文地址:https://blog.csdn.net/u013053268/article/details/134031218