1、C语言中的宏定义

  #define是预处理器处理的单元实体之—

  #define定义的宏可以出现在程序的任意位置

  #define定义之后的代码都可以使用这个宏

2、定义宏常量

  #define定义的宏常量可以直接使用

  #define定义的宏常量本质为字面量

下面的宏常量定义正确吗?

 #define ERROR -1   
  
#define PATHl "D:\test\test.c"   
  
#define PATH2 D:\test\test.c   
  
#define PATH3 D:\test\   
test.c  

3、实例分析

宏定义分析     21-1.c

 #define ERROR -1  
#define PATH1 "D:\test\test.c"  
#define PATH2 D:\test\test.c  
#define PATH3 D:\test\  
test.c  
  
int main()  
{  
    int err = ERROR;  
    char* p1 = PATH1;  
    char* p2 = PATH2;  
    char* p3 = PATH3;  
}  

预处理器不会进行语法检查只是简单的文本替换,即这些宏定义都正确!!但编译器会报错!!

4、宏定义表达式

  #define表达式的使用类似函数调用

  #define表达式可以比函数更强大

  #define表达式比函数更容易出错

下面的宏表达式定义正确吗?

  

 #define _SUM_(a, b) (a) + (b)   
  
#define _MIN_(a, b) ((a) < (b) ? (a) : (b))   
  
#define _DIM_(a) sizeof(a)/sizeof(*a)  

5、实例分析

宏表达式分析     21-2.c

 #include <stdio.h>  
  
#define _SUM_(a, b) (a) + (b)  
#define _MIN_(a, b) ((a) < (b) ? (a) : (b))  
#define _DIM_(a) sizeof(a)/sizeof(*a)  
  
  
int main()  
{  
    int a = ;  
    int b = ;  
    int c[] = {};  
  
    int s1 = _SUM_(a, b);  
    int s2 = _SUM_(a, b) * _SUM_(a, b);  
    int m = _MIN_(a++, b);  
    int d = _DIM_(c);  
  
    printf("s1 = %d\n", s1);  
    printf("s2 = %d\n", s2);  
    printf("m = %d\n", m);  
    printf("d = %d\n", d);  
  
    return ;  
}  

6、宏表达式与函数的对比

  宏表达式被预处理器处理,编译器不知道宏表达式的存在

  宏表达式用“实参“完全替代形参,不进行任何运算

  宏表达式没有任何的“调用”开销

  宏表达式中不能出现递归定义

 #define _SUM_(n) ((n > 0) ? (_SUM_(n-1) + n): 0) //error

 int s = _SUM_();

7、有趣的问题

宏定义的常量或表达式是否有作用域限制?

下面的程序合法吗?

 void def()   
{  
    #define PI 3.1415926   
    #define AREA(r) r*r*PI  
}  
  
double area(double r)   
{  
    return AREA(r);  
}   

8、实例分析

宏的作用域分析     21-3.c

 #include <stdio.h>  
  
void def()  
{  
    #define PI 3.1415926  
    #define AREA(r) r * r * PI  
}  
  
double area(double r)  
{  
    return AREA(r);  
}  
  
int main()  
{  
    double r = area();  
  
    printf("PI = %f\n", PI);  
    printf("d = 5; a = %f\n", r);  
      
    return ;  
}  

9、强大的内置宏

  
  __LINE__ 表示当前行号,整型值
  __FILE__ 表示当前文件名,字符串类型
  __DATE__ 编译的日期,字符串类型
  __TIME__ 编译的时间,字符串类型
  __STDC__ 预定义的宏

10、实例分析

宏使用综合示例     21-4.c

 #include <stdio.h>  
#include <malloc.h>  
  
#define MALLOC(type, x) (type*)malloc(sizeof(type)*x)  
  
#define FREE(p) (free(p), p=NULL)  
  
#define LOG(s) printf("[%s] {%s:%d} %s \n", __DATE__, __FILE__, __LINE__, s)  
  
#define FOREACH(i, m) for(i=0; i<m; i++)  
#define BEGIN {  
#define END   }  
  
int main()  
{  
    int x = ;  
    int* p = MALLOC(int, );  
      
    LOG("Begin to run main code...");  
      
    FOREACH(x, )  
    BEGIN  
        p[x] = x;  
    END  
      
    FOREACH(x, )  
    BEGIN  
        printf("%d\n", p[x]);  
    END  
      
    FREE(p);  
      
    LOG("End");  
      
    return ;  
}  

11、小结

  预处理器直接对宏进行文本替换

  宏使用时的参数不会进行求值和运算

  预处理器不会对宏定义进行语法检查

  宏定义时出现的语法错误只能被编译器检测

  宏定义的效率高于函数调用

  宏的使用会带来—定的副作用

C语言-宏定义与使用分析的更多相关文章

  1. C 语言宏定义

    C 语言宏定义1.例子如下: #define PRINT_STR(s) printf("%s",s.c_str()) string str = "abcd"; ...

  2. 将C语言宏定义数值转换成字符串!

    将C语言宏定义转换成字符串! 摘自:https://blog.csdn.net/happen23/article/details/50602667 2016年01月28日 19:15:47 六个九十度 ...

  3. C语言 宏定义之可变参数

    可变参数宏定义 C99编译器标准允许你可以定义可变参数宏(variadic macros),这样你就可以使用拥有可以变化的参数表的宏.可变参数宏就像下面这个样子: #define dbgprint(. ...

  4. c语言宏定义

    一. #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能理解该命令的本质,总是在此处产生一些困惑,在编程时 ...

  5. C语言宏定义#define用法

    #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质,总是在此处产生一些困惑,在编程时误用 ...

  6. C 语言宏定义函数编写时 do-while 的妙用和一些注意事项

    在 C 语言中,我们都知道可以用宏定义来编写函数,一般称为宏函数.如果一个宏函数比较复杂,那么在编写这样的宏函数是有一定技巧和注意事项的.文章给出一些我认为值得关注的地方,以及一些注意事项(个人建议) ...

  7. C语言宏定义时#(井号)和##(双井号)的用法1

    #在英语里面叫做 pound 在C语言的宏定义中,一个#表示字符串化:两个#代表concatenate 举例如下: #include <iostream> void quit_comman ...

  8. C语言宏定义时#(井号)和##(双井号)的用法

    C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结. 关于#和## 在C语言的宏中,#的功能是将其后面 ...

  9. C语言宏定义相关

    写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性 等等.下面列举一些成熟软件中常用得宏定义......1,防止一个头文件被重复包含#ifndef COMDEF_H# ...

随机推荐

  1. P2919 [USACO08NOV]守护农场Guarding the Farm

    链接:P2919 ----------------------------------- 一道非常暴力的搜索题 ----------------------------------- 注意的是,我们要 ...

  2. Selenium实战(四)——unittest单元测试2(断言方法+discover()多测试用例的执行)

    一.断言方法 方法 检查 版本 assertEqual(a,b) a==b   assertNotEqual(a,b) a!=b   assertTrue(x) bool(x) is True   a ...

  3. 吴裕雄--天生自然 python开发学习笔记:解决No module named 'mpl_toolkits.basemap'问题

    . 下载: basemap-1.1.0-cp36-cp36m-win_amd64.whl和pyproj-1.9.5.1-cp36-cp36m-win_amd64.whl这两个文件 先运行: 再运行:

  4. PP: Time series anomaly detection with variational autoencoders

    Problem: unsupervised anomaly detection Model: VAE-reEncoder VAE with two encoders and one decoder. ...

  5. phpcms v9全站点击量排行代码

    前台: <ul> {pc:content action="sitehits" siteid="1" num="10" order ...

  6. 敌兵布阵 HDU - 1166 板子题

    #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> ...

  7. 判断合同金额是否可以转整形和sql语句中添加条件语句

    主要用到sqlserver语句中的判断语法 if (min_hetonge.Length > 0 && int.TryParse(min_hetonge, out min)) s ...

  8. 问题 E: Problem B

    #include <cstdio> #include <cstring> #include <algorithm> #include <vector> ...

  9. 关于SkinTextBox中SkinTxt的事件使用

    SkinTxt的事件中的事件不能像一般的事件那样在属性中直接双击生成,它里面的事件都需要进行一定的转换间接使用,具体用法如下: 1.手动编写事件需要做的操作的方法 public void txtCod ...

  10. ECMAScript规范中第六大基本类型 Symbol

    初步了解第六大基本类型Symbol 概述: 什么是Symbol.Symbol是一个标记,一个独一无二的记号. Symbol的出现主要是解决了以前ES5中两个问题 在属性中同名的属性会被覆盖 无法做到属 ...