最近在linux平台做了一点开发,对嵌入式开发中有这样一些总结和思考,这些思考和总结也不全是针对嵌入式开发,在平时的应用软件开发中也会遇到。其中有些点是早就有人总结了,但是自己并未深刻意识到它们的意义,在最近的开放中,遇到了与它们相关的问题,感触就相对加深了,因此也拿来总结一下。
1、尽量不要混合使用C和C++,开发过程要尽量规范统一,要用C++就全用C++要用C就全部用C。
常见的需要注意和了解的地方有:
1) C中没有对象的概念,它只支持简单的struct,union等,
2) C的struct跟C++中的struct不一样,C++中的struct就是默认值为public类型的class,它像class一样有构造函数、析构函数;但是C中的struct就纯粹是把数据放在一起,它没有class的概念,也自然就不会有构造和析构函数了。
3) C的标准库头文件在使用时都要.h后缀,C++的基本都没有;例如:C的标准IO库文件为:#include<stdio.h>,包含了该头文件就可以使用printf进行输出了;而C++的标准IO库为#include<iostream>,包含了该头文件之后就可以使用cout进行输出操作了,当然,同时还要使用usingnamespace std来声明一下命名空间,如果不做此声明在使用时就得这样std::cout,必将麻烦。
4) 比较容易混淆的字符串操作库。
(1) 在C中,字符串操作的库函数头文件要如下包含:#include<string.h>(注意:这里有.h),在该库中包含了基于char*的字符串操作函数,例如strcpy等;注意该库里面没有定义string类。
(2) 在C++中,字符串操作的标准库函数要如下包含:#include<string>(注意:这里没有.h),在该库种定义了string类,该库队字符串的操作也都是基于string类;
(3) 因此开发过程中如果需要使用string类,就包含头文件:#include<string>,如果需要基于字符串指针char*操作就选择包含头文件:#include<string.h>
5) 在控制台输出时,如果是C开发就是用printf(定义在#include<stdio.h>中),如果用C++开发就用cout定义(在#include<iostream>中)。在一些嵌入式平台中,有时候对面向对象的支持并不好,如果混合使用printf和cout,则有可能造成程序卡死的问题,我曾在某嵌入式设备上5线程混合使用printf和cout进行测试,不到3个小时程序就出现卡死的问题了。因此在使用时尽量避免混用这两个不同库的输出函数。
2、函数使用的注意事项
1) 接口。模块对外的接口函数中,函数参数尽量传递指针(基本数据类型除外);模块内部函数参数传递中,尽量传递引用,引用就像变量一样使用,比指针使用起来要简单,而且还可以避免指针使用过程中出现的一些问题。
2) 函数命名。需要注意下面几点:
(1) 命名需要统一,例如,内部使用的私有函数以下划线“_”开头,函数名中的单词用首字母大小还是用”_”进行区分也报保持统一。
(2) 函数命名尽量按照“做什么而不是怎么做”的原则。
(3) 特殊函数需要保持成对出现,如果有了其中一个,即使另一个不需要也要尽量加上。例如:Init/UnInit、Open/Close、Start/Stop、Create/Destroy等。
(4) 不需要对外公开的私有函数尽量以”_”开头,例如类的私有成员函数或者模块内部定义的不需要导出给外部使用的函数都尽量保持此要求。
(5) 函数名的首字母要大写,这里也与变量命名要求相呼应。
3、 变量
1) 使用const常量或者枚举类型来代替数字、字符串、返回值等;避免在函数中突然出现一个莫名其妙的数字,它们通常被称为魔鬼数字,可见大家对其恐惧程度。如果只需要一个常量或者若干个相互之间没有关联的常量时使可以采用const来定义该常量,如果需要定义若干个相互之间存在关系的常量时可以采用枚举类型来定义这些相关常量。
例如:
(1) 在MFC中需要定义一个定时器的ID,则可以采用constint TIMER_ID = 1003;
(2) 需要为日志定义如下几个等级常量:EMERG、FATAL、ALERT、CRIT、ERROR、WARN、NOTICE,则可以采用union定义:
Enum ELevel
{
EMERG =0,
FATAL = 10,
ALERT = 20,
CRIT = 30,
ERROR = 40,
WARN = 50,
NOTICE = 60
}
2) 常量的名字尽量全部大写
3) 全局变量名用”g_”或”G_”开头,另外还要保持统一,既:要用”g_”就全部用”g_”,要用”G_”就全部用”G_”。
4) 类的成员变量名尽量以”m”或”m_”开头,如果是在windows下使用开发 就尽量使用”m_”开头。
5) 变量的首字母要小写,如有可能最好表示出其类型,例如:int iNum;char* pBuf;
4、 日志输出,在一些小项目中很少会去用log4cpp这样的大家伙来进行日志输出,大家一般都是自己使用printf或者cout直接输出。在日志输出时可参考以下建议:详情还可以参考另外的博文:http://houjixin.blog.163.com/blog/static/35628410201321810190631/
或:http://blog.csdn.net/hjx_1000/article/details/8685957
1) 统一日志输出,不要直接调用printf或cout进行输出;
2) 每个模块要输出自己的标签,以便定位问题。
3) 日志应可以开关
4) 日志应该言简意赅,长度不要超过一行。
5、 不要在构造函数中做太多的事情,构造函数如果异常就比较难定位,而且事情做得多出问题的可能性也就越大。此时可另外新建一个初始化函数boolInit()来完成初始化工作,当然同时也要定义相对应的UnInit()函数。