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. 【剑指Offer】58:二叉树的下一个结点

    题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 题解一:递归 //既然给了二叉树的某个结点,且二叉树存 ...

  2. ECMAScript基本对象——Math数学对象

    1.创建 不用创建直接使用.直接Math.方法名(): 2.方法 ①random():返回0.0-1.0的随机数,左闭有开 区间有开区间和闭区间,其中又分为全开区间( ),全闭区间[ ],左开右闭区间 ...

  3. 快速安装字体.bat批处理脚本

    因为经常要做些美工,暑假才换的笔记本上还没装什么字体,这次找到了字体资源,索性一次性装了~ 下载下来的字体包是\(.zip\)压缩文件,解压后如果一个个点\(.ttf\)文件来安装比较麻烦,所以写了一 ...

  4. GitHub概述

    1 引言 GitHub是为开发者提供Git仓库的托管服务,是一个让开发者与同事.同学及相同兴趣爱好者共享代码的完美场所. GitHub公司总部位于美国旧金山,拥有一只似章鱼又似猫的吉祥物. GitHu ...

  5. Dart单例模式最佳实践

    /// Created by Capt. Michael @ CaptNotes.com on 02/17/2020. class Singleton { Singleton._(); static ...

  6. 文件分配表(FAT)及其结构

    原链接:https://blog.csdn.net/qianjintianguo/article/details/712590?utm_source=blogxgwz6 文件分配表(FAT)是文件管理 ...

  7. 软件工程概论,java web项目

    需要网站系统开发需要掌握的技术: 实施Java的WEB项目需要掌握的技术如:面向对象分析设计思想,设计模式和框架结构,XML语言,网页脚本语言,数据库,应用服务器,集成开发环境Java语言是完全面向对 ...

  8. IP地址分类及其相关计算问题

    IP地址分类及其相关计算问题 公网IP和子网IP 公网IP: • A类:1.0.0.0 到 127.255.255.255 主要分配 给大量主机而局域网网络数量较少的大型网络 • B类:128.0.0 ...

  9. 远程执行命令_python

    一.远程执行命令模块subprocess Python可以使用subprocess下的Popen类中的封装的方法来执行命令 构造方法 popen() 创建popen类的实例化对象 ··· obj = ...

  10. 机器学习作业(三)多类别分类与神经网络——Matlab实现

    题目太长了!下载地址[传送门] 第1题 简述:识别图片上的数字. 第1步:读取数据文件: %% Setup the parameters you will use for this part of t ...