
2011
1. 宏定义和函数之间的区别
--------------------------------------------------- -------------------------------------------------- ------------------
宏: 宏定义是C提供的三个预处理功能之一. 这三个预处理包括:
(1)宏定义
(2)文件包含
(3)有条件编译
1. 不带参数的宏定义:
格式: #define标识符字符串
标识符是可以替换字符串的宏的名称. 编译器扩展了在预处理过程中替换宏的位置,并将宏名称替换为“字符串”. 这样做的好处是它可以用于数字或随机值. 指定代表名称以提高程序的可读性和性. 在以后的维护中,您可以轻松地在宏定义或其他数字类型中修改字符串的数字大小,以便可以控制整个代码中对宏名称的所有引用. 本地的.
从占用资源的角度来看,编译器不会占用或分配用于替换宏的内存. 与功能相比,调用子功能需要分配内存并增加系统开销,但是子功能可以使程序结构模块化并改善程序的功能. 相反,对于可读性和聚合而言,宏也可以具有参数. 如果为了不调用子函数而减少了开销,则所有过程都写在一个函数中,并且没有自注释名称,该程序的可读性将降低. 毕竟,代码是处理现实世界中事务数据关系的抽象,但它不是人类. 它应该像一本简洁优美的诗歌,描述了一笔美好的交易,所以妥协. ,宏替换是一个不错的选择.
尽管宏替换占用了编译器的时间,但是所谓的“无论得失”都减少了程序执行的资源消耗,这不是一个平衡.
宏的一些特征(参考):
(1)宏名称通常使用大写字母
(2)宏的使用可以提高程序的性和可读性,减少不一致,减少输入错误并便于修改. 例如,通常使用数组大小的宏定义. 可以理解,数组大小代表具体含义,便于二次维护.
(3)预处理是在编译之前进行处理,编译工作的任务之一是语法检查,而预处理不进行语法检查.
(4)宏定义的末尾没有分号;
(5)宏定义写在函数的花括号,通常在文件的开头. (6)您可以使用#undef命令终止宏定义的范围
(7)可以嵌套宏定义
(8)字符串“”将永远不包含宏
(9)宏定义不分配内存,变量定义分配内存.

具有参数的宏:
格式: #define S(r)r * r /////////
(1)如果实际参数是一个表达式,很容易出错
面积= S(a + b);第一步更改为area = r * r;,第二步更改为area = a + b * a + b;
正确的宏定义是#define S(r)((r)*(r)).
(2)宏名称和参数的括号之间不能有空格
(3)宏替换仅用于替换,无计算,无表达式解决方案
(4)在编译后运行程序并分配内存时进行函数调用. 宏是在编译前完成的,没有分配内存
(5)哑组合宏中没有类型,也没有类型转换.
(6)该函数只有一个返回值,您可以尝试使用宏获取多个值
(7)宏扩展使源程序更长,并且函数调用不会
(8)宏扩展不占用运行时间,仅占用编译时间,而函数调用占用运行时间(分配内存,保留场景,值传递和返回值.
(9): #define Uint unsigned int,即使用Uint代替unsigned int减少了写入长度,并且可以统一不同操作系统的公用变量标识.
语录: 宏定义其他不受欢迎且重要的知识(也在实际编程中使用)
(1)#定义名称“ zhangyuncong”
如果程序中有“ NAME”,它将被替换吗?
(2)#定义0x abcd
可以吗?换句话说,您可以用其他内容替换标识符的字母吗?
(3)#define NAME“ zhang
这可以吗?
(4)#定义名称“ zhangyuncong”

上面的宏定义在程序中,并且在程序中有一个句子:
NAMELIST,将其替换为“ zhangyuncong” LIST
所有四个问题的答案均为否定.
================================================ ==== ==================
首先,“”中的内容不会被宏替换. 其中大多数应该是已知的.
第二,宏定义之前的那个必须是有效的用户标识符
第三,宏定义并不意味着您以后可以编写任何内容. 您不能反汇编字符串中的两个“”.
第四: 仅替换标识符,不替换其他任何内容. NAMELIST是一个整体的标识符,并且没有NAME标识符,因此不会被替换.
也就是说,请记住在这种情况下: #define第一个位置第二个位置
(1)请勿替换程序中字符串的内容.
(2)首位只能是合法标识符(可以是关键字)
(3)如果第二个位置有字符串,则必须匹配“”.
(4)仅替换与第一个位置完全相同的标识符.
例如#define MAX(a,b)((a)>(b)?(a):( b))
遇到MAX(1 + 2,值)时,它将被替换为:
(((1 + 2)>(value)?(1 + 2):( value))
注意事项类似于没有宏的注意事项.
但是您仍然应该注意
#define FUN(a)“ a”
然后,FUN(345)将代替什么?
实际上,如果您编写此代码,则无论宏的实际参数是什么,它都不会影响被“ a”替换的命运.

也就是说,“”中的字符即使完全相同也不会用作构成参数.
那么,您会问,如果我要在此处输入FUN(345)并将其替换为“ 345”,我该如何实现?
请在下面查看#的用法
3. #在带有参数的宏定义中的用法
#define STR(str)#str
#用于在宏定义的参数两端添加字符串“”.
例如,这里的STR(我的#名称)将替换为“我的#名称”
通常,任何字符都可以用作形式参数,但是以下情况会导致错误:
STR())这样,编译器将不会将“)”作为STR()的参数.
STR(,)如上所述,编译器不会将“,”作为STR的参数.
STR(Ac预编译宏开关,B)如果实际参数太多,编译器将丢弃多余的参数. (以VC ++ 2008为例)
STR((A,B))将被解释为一个参数: (A,B),而不是被解释为两个参数,第一个是(A,第二个是B)
4. ##在人参宏定义中的用法
#define WIDE(str)L ## str
L将添加到形式参数str
的前面
例如: WIDE(“ abc”)将替换为L“ abc”
如果存在#define FUN(a,b)vo ## a ## b()
然后将FUN(id ma,in)替换为void main()
5. 多行宏定义:
#define doit(m,n)for(int i = 0; i <(n); ++ i)\

{\
m + = i; \
}
.
其中,在高焕堂的“ UML + OOPC嵌入式开发要点”中实现面向对象的轻量级方法中,使用了宏定义中的#define WIDE(“ abc”)L ## str的用法. ##和多行宏用法的定义.
因此,使用基于上述特征的良好宏定义可以编写漂亮的代码,防止程序中出现不一致的错误,提高可移植性,可读性,并便于修改和维护. 只要所有引用宏定义的位置都可以修改一次,就可以完成.
此外,在许多源代码中,一些宏是函数名. 直接重新定义函数名称,提高代码的可读性.
有条件的编译: 在开始时,它也可能是为了方便改进程序的设计. 源程序中的某些内容仅在特定条件下编译,因此出现条件编译,并引用Wikipedia. “通常,源程序文件中的所有行都参与编译. 但是有时您只想在满足某些条件时才编译部分内容,也就是说,指定部分内容的编译条件,即设置条件编译语句时,需要考虑以下三个位置: 1)条件编译语句块和函数定义主体之间(在(.h)文件中)没有嵌套; 2)条件编译语句块嵌套在函数主体之外(主要在(.c)文件中); 3)条件编译语句块嵌套在函数主体中(主要在(.c)文件中). 编译指令将确定编译哪个代码,不编译哪个代码. 它可以基于表达式的值或是否定义了特定的宏来确定编译条件. “
控件开发可以是是否定义了宏名称或表达式的值c预编译宏开关,以确定是否编译代码的特定部分.
报价:
文件include命令的一般格式为: #include“文件名”或#include <文件名>
功能: 在预处理期间,将“文件名”指定的文件的内容复制到此文件,然后编译合并的文件.
用法: 避免重复劳动
说明:
1. 双引号和尖引号之间的区别: 双引号表示系统正在查找文件在当前目录中的目录.
系统指定查找其他目录的标准方法;右引号仅搜索系统标准方式指定的目录.
2. #define只能指定一个包含文件. 如果要将多个文件嵌入到源文件中,则必须使用多个#define.
3. C语言允许嵌套使用#define.
在file1.c文件中,有一个包含命令#include“ file2.c”的文件. 预处理时,首先将file2.c的内容复制到文件中
file1.c,然后编译file1.c.
从理论上讲,只要将这些文件的内容扩展为符合C语言语法,#include命令就可以包含任何类型的文件.
2. 包含的文件及其所属的文件在经过预处理后会变成文件,因此,如果包含的文件中定义了全局变量,
不必在文件中使用extern关键字声明它. 但通常不要在包含的文件中定义变量.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/dianqi/article-221447-1.html
枷锁在一根根往自己脖子上套
唉
你家赵薇呢