宏定义

预处理

 预处理是程序编译前的一个预先处理的动作,编译一共有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	" , PI); 
      int a = 100 + PI ; 
      printf("a:%d
", a);
} 

输出:PI:3.141592    a:103

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

无参宏

 无参宏意味着我们在使用的时候不需要传递参数

#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	" , MAX(100,998) );  
      printf("%d
" , 100>998 ? 100 : 998 ); 
} 
输出:998      998

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

带参宏的副作用

 由于宏只是存粹的文本替换,中间不涉及任何的计算与语法检查,类型匹配,所以用起来会比用函数麻烦很多。

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

int main (int argc, char const *argv[])
{
      int x = 100;
      int y = 200; 
      printf("MAX:%d
" , MAX(x,y == 200 ? 888:999 ) ); 
}

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

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

所以应该修改长如下:

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

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

原文地址:https://www.cnblogs.com/ding-ding-light/p/14094479.html