宏的基本使用规范
来源:互联网 发布:asp塔配哪种网站数据库 编辑:程序博客网 时间:2024/06/04 18:48
宏的命名
说明:全大写字母,下划线分隔。可加上简短的模块名作为前缀。
原因:名称清晰,符合通常的规范,避免宏定义重复,防止冲突。
严禁在宏定义中进行数组、结构、字符串变量的定义
原因:函数中对宏的多次引用,会导致实际局部变量空间成倍放大
按照宏的功能、模块进行集中定义
说明:在一个地方将常量数值定义为宏,其他地方通过引用该宏,生成自己模块的宏。严禁相同含义的常量数值,在不同的地方定义为不同的宏,即使数值相同也是不允许的(维护修改后,极易遗漏,造成代码隐患)。
原因:杜绝同类的宏,定义在不同的地方,导致维护困难
宏的名字全部采用大写字母与下划线、数字,且在前部包含模块、功能的信息
代码中所有非0,1的常量值,用宏进行代替(改进见下一条)
代码中所有非-1,0,1的数值,尽量用一个有意义的标识符代替
例子:/*宏定义法*/
#define PIE 3.14
/*常量定义法*/
const float PIE = 3.14;
/*枚举定义法*/
enum
{
PIE = 3
};
原因:1. 方便阅读、理解代码;
2. 修改、维护方便,只需改动定义即可,不需在代码中改动所有直接使用值的地方。
3. 运行效率不变
用常量适当替代(类似功能的)宏
例子:#define PIE 3.14
const float PIE = 3.14;
原因:1. 宏是在预编译时用定义值全程替换宏名的,这样在编译时编译器不知道宏名,报错不易理解;
2. 跟踪调试时显示值,而不是宏名;
3. 宏没有类型,不能做类型检查,不安全;
4. 宏没有作用域;
5. 常量和宏的效率同样高;
若宏值多于一项,必须使用括号
例子:#define ERROR_LENGTH (100+1)
原因:当宏用在表达式中时,防止运算符优先级导致的计算混乱
不要用分号结束宏定义
例子:#define MAX_CHANNEL_NUM 16;
原因:可能导致编译出错
用inline函数代替(类似功能的)宏函数
说明:不是绝对的!某些宏函数的用法独特,inline函数取代不了。当不想指明或不能指明参数类型时,宏函数更合适。
原因:1. 宏函数在预编译时处理,编译出错信息不易理解;
2. 宏函数本身无法单步跟踪调试,但某些编译器(为了调试需要)可以将inline函数转成普通函数;
3. 宏函数的入参没有类型,可以是任何东西,有时不安全;
4. inline函数会在目标代码中展开,和宏的效率一样高;
函数宏的每个参数都要括起来
例子:#define WEEKS_TO_DAYS(w) (w *7)
#define WEEKS_TO_DAYS(w) ((w) *7)
不带参数的宏函数也要定义成函数形式
例子:#define HELLO( ) printf(“Hello.”)
#define HELLO printf(“Hello.”)
原因:括号会暗示阅读代码者此宏是一个函数。
自定义数据类型,用typedef,而不是宏
例子:#define LONG_PTR long*
LONG_PTR pA, pB;
本意是想定义两个指针,但展开后相当于“long* pA, pB;”,所以pB不是指针,而是long型变量。用typedef消除宏的弊病:
typedef long* LongPtr_T;
LongPtr_T pA, pB;
原因:宏的最大特点(弱点)就是在预编译时做简单替换,没有任何语法约束在里面。看似被宏归为一类的一串语法元素,其实是一盘散沙,和宏之外的其他元素没有任何差别。这是导致期望和实际效果不符的主要原因。
使用宏防范头文件被多次引用
例子:#ifndef _OAM_MACRO_H
#define _OAM_MACRO_H
…
#endif
说明:1. 此类宏的命名,基本上可以和头文件的文件名相同。
2. 此类宏如果重名,会造成严重后果,为了保证唯一性,长一点无妨,不要缩写。
不要用宏改写语言
例子:#define FOREVER for ( ; ; )
#define BEGIN {
#define END }
原因:C语言有完善且众所周知的语法。试图将其改变成类似于其他语言的形式,会使代码阅读者混淆,难于理解。
编译宏一定要放在句首,不缩进
例子:……
case CMD_MODE_NPCIX_WAN_MODE:
#if defined(MP)
caseCMD_MODE_VBUI_INTERFACE:
#endif
#if INSTALL_EVENT_LINKAGE
case CMD_EXEC_EVT_LIST:
#endif
case CMD_MODE_TIMERANGE:
pOamMsg->out_index =pLinkState->out_index;
break;
原因:便于阅读、理解实际生效的代码。
用{ }或do{ }while(0)将函数宏的函数体括起来
原因:尽量保证宏函数作为一条独立的语句,不干扰别人,也不受别人干扰
说明:宏定义中使用do{}while(0)的原因及好处:
格式:#defineMACRO_NAME(para) do{…} while(0)
1. 避免空的宏定义产生warning:
#define foo( ) do{}while(0)
2. 存在一个独立的block,可以进行变量定义,实现比较复杂的逻辑处理。
3. 如果宏出现在判断语句之后,可以保证作为一个整体来实现:
#define foo(x) \
action1( ); \
action2( );
在以下情况下:
if (NULL == pPointer)
foo( );
就会出现action1和action2不会同时被执行的情况,这显然不是程序设计的原始目的。
4. 以上的3种情况,用单独的{}也可以实现,但是为什么一定要一个do{}while(0)呢?
看以下代码:
#define SWITCH(x, y) {int tmp;tmp="x"; x=y; y=tmp;}
if (x > y)
SWITCH(x, y);
else //error, parse error before else
OtherAction();
在把宏引入代码中,会多出一个分号,从而会报错。
使用do{...}while(0) 把它包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{...}while(0)这种无用的循环并优化,所以使用这种方法不会导致程序的性能降低。
- 宏的基本使用规范
- 前端代码的一些基本规范使用
- 基本的代码规范
- JavaScript的基本规范
- Javascript的基本规范
- 基本的编程规范
- 编程最基本的规范
- log系统的基本规范
- java编程的基本规范
- JavaScript 的基本代码规范
- JavaScript 的基本代码规范
- Html书写规范,基本标签使用
- [Redis]Redis 概述及基本使用规范.
- iOS宏定义的使用与规范
- iOS 宏定义的使用与规范
- iOS宏定义的使用与规范
- 基本数据类型、引用数据类型相互之间的比较规范(相等运算符的使用)
- block的使用规范:
- js实现在页面对列表的排序
- 遗传算法介绍(内含实例)
- 5.Libgdx扩展学习之Box2D_刚体的运动和贴图
- Beaglebone black 4G 调试中的问题
- 关于 iOS 10 中 ATS 的问题
- 宏的基本使用规范
- iOS10 适配 ATS(app支持https通过App Store审核)
- spring mvc maven工程创建
- 各大网站收录、搜索引擎的提交入口
- 第十五周项目2—用哈希法组织关键字
- Redis系列之(一):10分钟玩转Redis
- 游戏开发基础--碰撞检测
- git使用:创建初始版本库
- jquery点击添加样式