c语言中关于宏
2017-12-03 17:43
232 查看
我们在写c语言程序中,已经初步了解到了#define的用法,下面对#define做一个详细的用法说明。
有了这条指令之后,每当有name出现,就会被预处理器替换为stuff。
例:
如果定义中的stuff比较长,可以使用续行符分成几部分,如:
这里需要强调,在#define定义的标识符常量后不要加分号,这样做在某些状况下不会出错,但在大多数情况下容易出错,并且不好看出,所以不建议在宏定义之后加分号。
其中,参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。
举例说明:
乍一看,可能会觉得打印36这个值,事实上,会打印11这个值。
再次强调,宏替换只是简单的文本替换,所以实际上在程序中,被替换成了,a+1*a+1,怎么计算相信大家都会。
想要解决这个问题非常容易,在写宏时,尽可能多的带括号,比如写成下面的形式,
总结:所有用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时,由于参数中的操作符或邻近的操作符之间不可预料的相互作用。
在调用宏时,首先对参数进行检查,看看是否包含了#define定义的符号,如果是,他们首先被替换。
替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替代。
最后,再次对文本进行扫描,看看是否包含了由#define定义的符号,如果有,重复以上步骤。
但是,宏不可以出现递归。
在这里,可以得出一个技巧的例子:
实际上替换后就是:printf(“The value is %d\n”,x+3);
这种技巧只有当字符串常量作为宏参数给出时才能使用。
第二个技巧使用预处理器把一个宏参数转换为一个字符串。
例:
替换后即:
sum5+=25;注意这种连接必须产生一个合法的标识符,否则,其结果就是未定义的。
例如:
以一个MAX宏函数具体说明:
直接给出替换后的代码:
这样就能得出结果了吧
#define
格式如下:#define name stuff
有了这条指令之后,每当有name出现,就会被预处理器替换为stuff。
例:
#define reg register #define do_forever for(;;) #define CASE break;case
如果定义中的stuff比较长,可以使用续行符分成几部分,如:
#define DEBUG_PRINT printf("File %s line %d:"\ "x=%d,y=%d,z=%d,\ __FILE__,__LINE__,\ x,y,z)
这里需要强调,在#define定义的标识符常量后不要加分号,这样做在某些状况下不会出错,但在大多数情况下容易出错,并且不好看出,所以不建议在宏定义之后加分号。
宏
定义:#define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏。#define name(parameter-list) stuff
其中,参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。
举例说明:
#define SQUARE(x) x*x a=5; printf("%d\n",SQUARE(a+1));
乍一看,可能会觉得打印36这个值,事实上,会打印11这个值。
再次强调,宏替换只是简单的文本替换,所以实际上在程序中,被替换成了,a+1*a+1,怎么计算相信大家都会。
想要解决这个问题非常容易,在写宏时,尽可能多的带括号,比如写成下面的形式,
#define SQUARE(x) ((x)*(x))
总结:所有用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时,由于参数中的操作符或邻近的操作符之间不可预料的相互作用。
define替换
在程序中扩展#define定义符号和宏时,需要涉及以下几个部分:在调用宏时,首先对参数进行检查,看看是否包含了#define定义的符号,如果是,他们首先被替换。
替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替代。
最后,再次对文本进行扫描,看看是否包含了由#define定义的符号,如果有,重复以上步骤。
但是,宏不可以出现递归。
在这里,可以得出一个技巧的例子:
#define PRINT(FORMAT,VALUE) \ printf("The value is "FORMAT"\n",VALUE) ... PRINT("%d",x+3);
实际上替换后就是:printf(“The value is %d\n”,x+3);
这种技巧只有当字符串常量作为宏参数给出时才能使用。
第二个技巧使用预处理器把一个宏参数转换为一个字符串。
例:
#define ADD_TO_SUM(sum_number,value) \ sum##sum_number+=value ..... ADD_TO_SUM(5,25);
替换后即:
sum5+=25;注意这种连接必须产生一个合法的标识符,否则,其结果就是未定义的。
带副作用的宏参数
€当宏参数在宏定义中出现的次数超过一次时,如果这个参数具有副作用,那么当你使用这个宏时,就是不安全的,会导致不可预料的错误。副作用就是 在表达式求值时出现的永久性效果。例如:
x+1;//不带副作用 x++;//带有副作用
以一个MAX宏函数具体说明:
#define MAX(a, b) ( (a) > (b) ? (a) : (b) ) ... x = 5; y = 8; z = MAX( x++, y++); printf("x=%d y=%d z=%d\n", x, y, z); //输出的结果是什么?
直接给出替换后的代码:
z = ( (x++) > (y++) ? (x++) : (y++));
这样就能得出结果了吧
x=6; y=10; z=9;
命名约定
实际上,宏于函数的用法在某些情况写是非常不容易区分的,所以我们需要通过命名方式从外表来区分宏与函数。宏名全部大写 函数名不要全部大写
#define MAX(a,b) ((a)>(b)?(a):(b)) Max(a,b);
宏与函数
用摘自《c和指针》书中的一个表格来区分宏与函数。相关文章推荐
- C语言 关于结构体的内存对齐
- <志良电子>关于C语言中用Keil软件制作Lib库文件的几点经验
- 关于C语言中scanf函数的小结
- 关于c语言中static的个人遇到的小问题
- 【c语言】关于+1的各种情况
- 关于C语言中getopt()函数的使用方法
- 关于C语言中的malloc和free函数的用法(转载)
- 关于C语言中#define的副作用讨论 推荐
- C语言预处理功能——关于字符串化和符号粘贴
- 关于c语言中qsort函数的一点心得
- 关于C语言中加法的实现原理
- 关于c语言float型浮点数与double的区别
- 关于c语言传值与传址的理解
- 关于C语言指针
- 关于c语言编程中<>于“ ”的区别
- C语言中关于错误输出的函数
- 一个初学者的C语言学习之路——关于原反补码的一些认识
- 关于c语言的输入函数问题
- 关于C语言中a=a++与a=++a的研究
- 关于C语言中日期 计算问题