宏定义

预处理

 预处理是程序编译前的一个预先处理的动做,编译一共有4个步骤:C原文件 --> 预处理 --> 编译 --> 汇编 -> 连接 --> 可执行文件。
预处理的工做主要是展开咱们C源码中的#开头的语句,去掉了全部的注释,在严格的意义来讲,这些语句它并不属于C语言的语法范畴。
 如下是预处理的一些指令:
  1.头文件 : #include
  2.宏定义 : #define
  3.取消宏 : #undef
  4.条件编译 : #if \ #ifdef \ #ifndef \ #else \ #elif \ #enif
  5.显示错误 : #error
  6.修改当前文件的名字行号 :#line
  7.向编译器中发送特定的指令 : #progma
 能够在编译程序的时候添加一个-E的选项,让编译器在预处理以后停下来不要继续往下走,macro.i是源程序将#展开的内容。数组

gcc macro.c -o macro.i -E

宏的概念

 宏(macro)实际上以一段字串,在源码中只是用来直接替换目标位置,通常宏都使用全大写字母(这只是一个习惯)。函数

#define    PI           3.141592 
    #define    BUF_SIZE     64 
    int main (int argc, char const *argv[]){

       printf("PI:lf\t" , PI); 
       int a = 100 + PI ; 
       printf("a:%d\n", a);
   } 

输出:PI:3.141592    a:103

注意:
1.PI就是一个宏,在咱们的源代码中若是出现宏的使用,则经过预处理以后会直接被替换,只是直接的字符替换而已,不会考虑语法或运算关系。code

无参宏

 无参宏意味着咱们在使用的时候不须要传递参数内存

#define    BUF_SIZE     64 
    
    int main (int argc, char const *argv[]){
      
      int arr[BUF_SIZE];   //定义了一个int型数组,大小为64个
    }

注意:
1.宏他的本指就值直接的替换,没有任何的语法检查;
2.使用宏的状况下若是代码有跟新迭代时,只须要修改宏的一处,整个代码中全部用到宏的地方都会被修改;
3.宏的名字能够提升代码的可读性。编译器

带参宏

 带参宏 在使用的时候须要携带参数来使用。源码

#define MAX(a,b) a>b ? a : b 
    int main (int argc, char const *argv[]){
    
      printf("%d\t" , MAX(100,998) );  
      printf("%d\n" , 100>998 ? 100 : 998 ); 
    } 

输出:998      998

注意:
1.使用带参宏的时候也是直接替换。
2.只是存粹的文本替换,没有任何的语法检查/判断,也没有任何的运算
3.宏在预处理以后已经被替换,代码实际运行时是不须要额外的时间开销,只会浪费一点内存的空间。编译

带参宏的反作用

 因为宏只是存粹的文本替换,中间不涉及任何的计算与语法检查,类型匹配,因此用起来会比用函数麻烦不少。gcc

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

    int main (int argc, char const *argv[]){

      int x = 100;
      int y = 200; 
      printf("MAX:%d\n" , MAX(x,y == 200 ? 888:999 ) );

从以上的代码中, 无论表达式 y == 200 ? 888:999  的值都是大于 x ,可是却出来最大值为x 、
观察一下替换后的结果:语法

printf("MAX:%d\n" , x>y == 200 ? 888:999 ? x : y == 200 ? 888:999 );   //注意从右向左运算,?的优先级大于:

因此应该修改长以下:gc

#define   MAX(a,b)  (a)>(b) ? (a) : (b) 
    printf("MAX:%d\n" , (x)>(y == 200 ? 888:999) ? (x) : (y == 200 ? 888:999) );

使用括号对宏当中的每一项括起来,提升优先级,这样替换以后逻辑不会出现问题。

相关文章
相关标签/搜索