C语言-宏定义与使用分析
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语言-宏定义与使用分析的更多相关文章
- C 语言宏定义
C 语言宏定义1.例子如下: #define PRINT_STR(s) printf("%s",s.c_str()) string str = "abcd"; ...
- 将C语言宏定义数值转换成字符串!
将C语言宏定义转换成字符串! 摘自:https://blog.csdn.net/happen23/article/details/50602667 2016年01月28日 19:15:47 六个九十度 ...
- C语言 宏定义之可变参数
可变参数宏定义 C99编译器标准允许你可以定义可变参数宏(variadic macros),这样你就可以使用拥有可以变化的参数表的宏.可变参数宏就像下面这个样子: #define dbgprint(. ...
- c语言宏定义
一. #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能理解该命令的本质,总是在此处产生一些困惑,在编程时 ...
- C语言宏定义#define用法
#define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质,总是在此处产生一些困惑,在编程时误用 ...
- C 语言宏定义函数编写时 do-while 的妙用和一些注意事项
在 C 语言中,我们都知道可以用宏定义来编写函数,一般称为宏函数.如果一个宏函数比较复杂,那么在编写这样的宏函数是有一定技巧和注意事项的.文章给出一些我认为值得关注的地方,以及一些注意事项(个人建议) ...
- C语言宏定义时#(井号)和##(双井号)的用法1
#在英语里面叫做 pound 在C语言的宏定义中,一个#表示字符串化:两个#代表concatenate 举例如下: #include <iostream> void quit_comman ...
- C语言宏定义时#(井号)和##(双井号)的用法
C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结. 关于#和## 在C语言的宏中,#的功能是将其后面 ...
- C语言宏定义相关
写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性 等等.下面列举一些成熟软件中常用得宏定义......1,防止一个头文件被重复包含#ifndef COMDEF_H# ...
随机推荐
- java script 内置对象
java script 内置对象 Date 日期对象 字符串对象 定义字符串的方法就是直接赋值 使用 String 对象的 toUpperCase() 方法来将字符串小写字母转换为大写,反之 toLo ...
- 基于element-ui 模仿微信聊天页面以及滚动条隐藏在chrome和其他浏览器的处理
1.效果图 2.代码 <template> <div style=" overflow: hidden;"> <el-row> <el-c ...
- 【EasyUI总结】EasyUI开发中遇到的坑
普遍: 1.easyui在书写键值对的时候要注意是否要加引号,在需要加引号的地方不加则无法渲染: datagrid数据网格: 1.datagrid默认请求方式是post,如果要使用分页功能pagina ...
- clientHeight offsetTop scrollTop
- 忽略npm install安装失败信息
在package.json目录下运行npm install命令时会提示某些模块安装失败,如下图所示: 不管你在.npmrc文件中设置了proxy.https-proxy和registry地址,它还 ...
- 【剑指Offer】01、二维数组中的查找
题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...
- Docker构建镜像过于缓慢解决-----Docker构建服务之部署和备份jekyll网站
参考原文链接:https://www.jianshu.com/p/e6b7e68f2ba7 来自<第一本Docker书>,我觉得很有趣,就记录一下 准备国内ubuntu镜像 每次构建Ubu ...
- 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 ...
- arm的字节对齐问题总结(转)
问题由来:pc的lsb总是0,因为代码至少要字对齐.cm3的指令至少是半字对齐的(16) 一.啥是字对齐?为啥要字对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访 ...
- svn提交更新代码提示Please execute the 'Cleanup' command 的解决办法
那可能是提交或更新代码的过程意外终止,第二次提交或更新会报这个错误 更新或上传的时候动作没有完成,导致本地存在锁定状态没有释放 或者有文件正在更新或上传,该文件夹被锁定. 解决办法: 将对应文件夹里的 ...