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. java script 内置对象

    java script 内置对象 Date 日期对象 字符串对象 定义字符串的方法就是直接赋值 使用 String 对象的 toUpperCase() 方法来将字符串小写字母转换为大写,反之 toLo ...

  2. 基于element-ui 模仿微信聊天页面以及滚动条隐藏在chrome和其他浏览器的处理

    1.效果图 2.代码 <template> <div style=" overflow: hidden;"> <el-row> <el-c ...

  3. 【EasyUI总结】EasyUI开发中遇到的坑

    普遍: 1.easyui在书写键值对的时候要注意是否要加引号,在需要加引号的地方不加则无法渲染: datagrid数据网格: 1.datagrid默认请求方式是post,如果要使用分页功能pagina ...

  4. clientHeight offsetTop scrollTop

  5. 忽略npm install安装失败信息

    在package.json目录下运行npm install命令时会提示某些模块安装失败,如下图所示:   不管你在.npmrc文件中设置了proxy.https-proxy和registry地址,它还 ...

  6. 【剑指Offer】01、二维数组中的查找

    题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...

  7. Docker构建镜像过于缓慢解决-----Docker构建服务之部署和备份jekyll网站

    参考原文链接:https://www.jianshu.com/p/e6b7e68f2ba7 来自<第一本Docker书>,我觉得很有趣,就记录一下 准备国内ubuntu镜像 每次构建Ubu ...

  8. PAT (Advanced Level) Practice 1011 World Cup Betting (20 分) (找最值)

    With the 2010 FIFA World Cup running, football fans the world over were becoming increasingly excite ...

  9. arm的字节对齐问题总结(转)

    问题由来:pc的lsb总是0,因为代码至少要字对齐.cm3的指令至少是半字对齐的(16) 一.啥是字对齐?为啥要字对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访 ...

  10. svn提交更新代码提示Please execute the 'Cleanup' command 的解决办法

    那可能是提交或更新代码的过程意外终止,第二次提交或更新会报这个错误 更新或上传的时候动作没有完成,导致本地存在锁定状态没有释放 或者有文件正在更新或上传,该文件夹被锁定. 解决办法: 将对应文件夹里的 ...