c语言define的使用方法总结


原文链接: c语言define的使用方法总结

#和##有什么区别? 他们都不会将参数进行展开

1. # 的作用是将宏定义中的参数转换成“字符串”  #define STR(x) #x  => a=1; STR(a) "a"
2. ##的作用是将宏定义中的参数变成字符串并连接到一起,主要用于添加前后缀等
    #define PI 3.14
    #define STR(x) #x           => a=1; STR(a) "a"
    #define CONECT(x,y) x##y    =>  
    
CONECT(1,2) ==> 12
CONECT(P,I) ==> 3.14
STR(PI)     ==> "PI"

原来以为什么是宏?无非就是定义一个替换的量,好比 #define PI 3.1415926,这样的功能,再深一点就是写一个类似函数的定义,好比 #define MAX(a,b) ((a) > (b) ? (a) : (b)) 这样的功能,再问一下宏是什么?无非就是预处理阶段所要展开的乱七八糟的东西,其实也就知道这么点,当看了 Linux Kernel Code,其实会发现自己懂得那些其实都是皮毛,不值一提的小东西,才发现自己 OUT 了,为此博主将 #define 的使用方法总结了一下,如下所示:(如有不足请批评指正)

  1. 最最最简单的 define 定义
        不赘述了,说一下其他的吧,如 #define MAX 10,编译器在处理这个代码之前会对 MAX 进行处理,替换为 10,或许有些人认为这样的定义看起来和 const 常量很相似,但是他们还是有区别的,#define 的定义其实就是简单的文本的替换,并不是作为一个量来使用

  2. 用 #define 来对函数进行 “定义”**
        很多就会问了,什么?居然还能用 #define 来定义函数,坑爹么?其实咋说呢,就是类似的一个函数定义罢了,和真正的函数定义当然还是有区别的了,下面进行举例说明:

   还是用上面的 MAX 的例子:#define MAX(a,b) ((a) > (b) ? (a) : (b)),这个定义就返回两个数中较大的那个,不知道你们看到了没看到,这个” 函数 “没有类型检查,像不像函数模板?像?不像?
    其实是有点像的,可以作为一个普通的模板来使用罢了,他肯定没函数模板那么安全,WHY?看下面的例子:

    #define MINUS(a,b) a - b, 眨眼一看,这个肯定是减法操作的 define,有木有?对,没错,就是这个意思,这个定义在一般的使用中没问题,但是在特定的情况下使用会出现问题,如果我们要这样去使用     的话,展开之后会是什么样子呢?如:2 * MINUS(a,b) / 4,就像我前面所说的那样,宏其实就是一个简单的文本替换,所以展开时候就变为 2 * a - b / 4,和我们想要的结果是不是不一样?是不是错         了?有木有?那要如何解决这个问题呢,很简单,给原定义加一个括号就 OK 了,也就是 #define MINUS(a,b) (a - b)

    再说一个经常出现的一个错误,看下面的例子:
    #define pin (int *)
    pin a,b;
    本意其实都想让 a 和 b 成为 int 型指针,但是实际上却变成了 int *a,b;a 是 int 型指针,b 是 int 型变量,咋处理捏?这个时候 typedef 就出来了,它说我可以满     足 define 满足不了的要求,所以改成
    typedef pin (int *) 就 OK 了。

    TIP:我们在写 code 的时候一定要养成一个良好的习惯和一个良好的代码编写风格,建议所有的层次都加上括号

  1. define 的单行定义,举例说明之,属于少见用法
        #define A(x) ##x
        #define B(x) #@x
        #define C(x) #x
        如果我们假设 x=1,那么 A(1) 就是 1,B(1) 就是‘1’,C(1) 就是”1“
  2. define 的多行定义
        #define 可以进行多行定义,虽然看起来有点蛋疼,但是确实是一个灰常经典而且在设备驱动代码中经常要用到的一个方法,格式如下:
        #define MACRO(arg1,arg2) do {  
        test1;
        test2;
        }while(0)

    TIP: 在每一行的末尾要加上 \,切记!

  1. 定义宏和取消宏定义的方法
        定义一个宏使用 #define,取消一个宏定义使用 #undef

  2. 使用宏进行条件编译
        格式如下:#ifdef ... (#else) ... #endif
        如:
        #ifdef HELLO
        #define WORLD 1
        #else
        #define WORLD 0
        #endif

  3. 用 define 来处理头文件被头文件或者源文件包含的情况
        由于头文件包含可以嵌套,那么 c 文件有可能包含多次同一个头文件,就会出现重复定义的问题的,那么可以就通过条件编译开关来避免重复包含,如下:
        #ifndef _HELLOH
        #define _HELLOH
        ...
        // 文件内容
        ...
        #endif

`