宏定义笔记
来源:互联网 发布:淘宝能买到氰化钾吗 编辑:程序博客网 时间:2024/06/05 13:25
宏定义有两种:简单宏定义,带参数的宏定义。
简单宏定义:#define 标识符 替换列表
#define
为常量命名的优点:
1. 程序会更易读;
2. 程序更易于修改;
3. 可以帮助避免前后不一致或键盘输入错误;
其他应用:
1. 可以对C语法做小的修改:
#define BEGIN { // 指令总在第一个换行符结束,除换行符之前加 \#define END } // 之间的空格符是可以任意的
甚至可以定义: #define LOOP for( ;; )
2.对类型重命名:#define BOOL int
但是,通常使用typedef 对类型重命名
3.控制条件编译:
带参数的宏定义 #define 标识符(x1,x2,x3,...,xn) 替换列表
如:
#define MAX(x,y) ((x)>(y) ? (x) :(y))//替换列表中的参数都使用()括起来,可避免之间优先级不同而出错
可以包含空的参数列表: #define getchar() getc(stdin)
优点:
程序可能会稍微快些。一个函数调用在执行时通常有些额外开销—–储存上下文信息,复制参数的值等。而宏的调用没有。
宏会更”通用”。 与函数的参数不同,宏的参数类型没有类型。因此,只要预处理后的程序合法,宏可以接收任何类型的参数。
缺点:
编译后代码通常会增加。
宏参数没有类型检查。预处理器不会检查宏参数类型,也不会进行类型转换
无法用一个指针来指向一个宏。宏在预处理的过程中被删除,所以不存在类似的“指向宏的指针”。
宏可能会不止一次地计算它的参数。如果参数有附加作用,多次计算参数的值可能会产生意外的结果。例如: n = MAX(i++,j);
即n = ((i++)>(j)?(i++):(j));
如果i>j, 那么i可能会被计算两次,结果n被赋错误值。
因此,为避免这种情况,最好不使用带有附加作用的参数。
#运算符
将一个宏的参数转换为字符串字量。它仅允许出现在带参数的宏的替换列表中。
例如: #define PRINT_INT(x) printf(#x " = %d\n", x)
x之前的#通知预处理器根据 PRINT_INT 的参数创建一个字符串字面量。因此,调用 PRINT_INT(i/j);
会变成printf("i/j"" = %d\n",i/j);
等价于 printf("i/j = %d\n",i/j);
##运算符
##运算符
可以将两个记号连在一起,成为一个记号。例如,#define MK_ID(n) i##n
int MK_ID(1),MK_ID(2),MK_ID(3);
等价于int i1,i2,i3;
##
用于同一功能,不同数据类型的函数的宏定义,如:
#define GENERIC_MAX(type) \type type##_max(type x, type y) \{ \ return x>y?x:y; \}
则GENERIC_MAX(float)
等价于 float float_max(float x,float y) {return x>y?x:y;}
逗号运算符
在创建较长的宏时, 逗号号运算符很有用。可以用逗号运算符使替换列表包含一系列表达式,如: #define ECHO(s) (gets(s), puts(s))
而,如果想在宏的替换列表中包含一系列语句,可以用do{...}while(0)
,如:
#define ECHO(s) \ do { \ gets(s); \ puts(s); \}while(0)
注意:在使用ECHO宏时,一定要加分号:ECHO(str);
预定义宏
_LINE_
被编译文件行数 _FILE_
被编译文件名字 _DATE_
编译的日期(m d y) _TIME_
编译时间(h:m:s) _STDC_
如果编译器接受标准C,那么值为1其中,_LINE_
和_STDC_
是整型常量,其他3个宏是字符串字面量。 _DATE_
和_TIME_
指明程序编译时间:
printf("Linux (c) 2017 King Software,Inc.\n");printf("Complied on %s at %s\n, _DATE_, _TIME_");
程序开始执行,都会打印编译的日期和时间,可以用来区分同一程序的不同版本。 _LINE_
和_FILE_
可以用来找错误。当一个c程序因为被0除(或被0余)而导致终止时,通常没有信息指明哪条除法(或余)导致错误。下面的宏可以帮助查明错误的根源:
#define CHECK_ZERO(divisor) \ if(divisor == 0) \ printf("***Attempt to divide by zero on line %d of file %s ***\n", _LINE_, _FILE_);
CHECK_ZERO宏应该在(余)除法运算前被调用:
CHECK_ZERO(j);k = i/j;
如果j = 0,显示错误位置。
C语言库提供了一个通用的、用于错误检测的宏——assert宏。
条件编译
#if & #endif
#define DEBUG 1#if DEBUG....#endif
如果DEBUG设为1,预处理器就将#if 与 #endif 之间的语句保留到程序中,进行编译;如果DEBUG设为0,预处理器就删去此段代码。
对于没有定义过的标识,#if 将它视为0。
defined运算符
使用:defined 标识符
如果标识符已经定义为宏返回1,否则返回0。
#define DEBUG //不需要给定值#if defined DEBUG....#endif
#ifdef & #ifndef
#ifdef //相当于#if defined
#ifndef //相当于#if !defined
#elif & #else
#if 标识符#if 表达式1#elif 条件1#elif 条件2....#else#endif
elif
可以多次使用,else
只能在其中使用一次。
使用条件编译的好处:
编写多台机器或者多个操作系统的可移植程序。
#if defined WINDOWS....#elif defined UNIX....#elif defined OS....#endif
编写可以使用不同编译器编译的程序。
#if _STDC_ //标准c函数原型....#else //经典c函数声明....#endif
为宏提供默认定义。
#ifndef BUFFER_SIZE#define BUFFER_SIZE 256#endif
临时屏蔽包含注释的代码。由于在标准C中不能用注释嵌套
#if 0包含注释的代码行#endif
未完
- 宏定义笔记
- 【学习笔记】宏定义基础
- 整理摘抄 宏定义笔记
- C\C++宏定义笔记
- asterisk学习笔记7--宏定义规则
- OpenCL学习笔记 - 关键字 宏定义
- Cocos2dx 学习笔记22 常用宏定义
- C语言笔记之宏定义
- iOS开发笔记---objective-c宏定义
- 黑马程序员---学习笔记13:宏定义
- 宏定义-C语言基础学习笔记
- c语言学习笔记之宏定义
- 【C++笔记】宏定义数据类型与typedef
- ios笔记--宏定义,条件编译和文件导入笔记
- 笔记 :定义二维数组
- js数组定义笔记
- 笔记5 定义函数
- MTK平台源码学习笔记之-------宏定义的学习
- 改变NumberPicker文字,分割线的颜色
- AOP切面用aspectjweaver.jar实现代码
- JAVA基础
- 获取2个特定字符串之间的内容【Android】
- js解析机制分析
- 宏定义笔记
- Android系统进程间通讯之Binder机制(二)
- bootstrap工具提示
- caffe学习
- 实验:C++实验6-矩阵求和
- Educational Codeforces Round 21 A. Lucky Year
- 时间字符串string转换为时间格式nsdate
- MYSQL基本操作(2)-数据表的操作
- 复习