文件读写是经常用到的操作,一般在标准库里,有些系统,比如Windows,在系统库里也有,如CreateFile/ReadFile/WriteFile。可以肯定的是,最好不用用MFC库里的CFile系列,当然,如果你的代码本身就基于MFC,则本文可能并不适合你。
也不要以为fopen/fclose是安全的,因为有一些嵌入式系统上不支持这些最普通的函数。
Fputs/fgets能不用,尽量不要用。
Char, Short, int, long, …..不要忽视这些基础类型,就是这些类型,有时也能让人痛苦不堪。
因为他们所表示的数据占用的存储空间的确切大小,并不是永远不变的,在不同的系统里,也许有细微的差别。尤其是long, 有一些系统里是32位,另一些系统里却表示64位的数值。
再说char, 也许你觉得它是代表signed char,其实,有的系统里他代表unsigned char.。如果不注意,总有一天会让你郁闷无比。
有许多编译环境,内部用宏定义或typedef的形式提供了许多特别的数据类型。比如VC里,用ULONG可表示unsigned long, UINT可表示unsigned int,尽量不要用这种形式的类型。因为,许多其它的编译环境并没有提供这些附加的类型定义。
对于提高可移植性来说,对外接口是一个需要注意的方面。无论是开发COM组件,静态库还是动态库,你也许永远无法估计将来你的开发成果会被应用于什么哪些环境。
能用C语法描述的,尽量不要采用C++的语法描述,除非你的老板强制要求你必须使用C++。 假如你开发了一个动态库,大量接口采用了C++的语法,而老板的一个重要客户的开发环境或者工程里都是C,那么无疑为自己增加繁琐而无谓的工作量,而且仓促间完成的转换接口,很容易成为出现问题时被怀疑的对象。
如果必须采用C++作为接口,那么请记得,接口就是接口,只是接口而已。请永远不要在你的.h文件里提供类的数据成员,不管是private和protected还是public,除非你打算同事公开对应的.cpp文件;当然,简单的只包含内联成员函数的类除外。如果你非要公开你的数据成员不可,那么请保证永远不要修改这个类的实现。你能保证你绝对不会添加或者删除或者修改这个类的数据成员吗?
请确保你的类的成员函数有一个清晰的排列次序。因为一旦你的类有了一个客户,再要去修改这个次序是非常危险的,即使你足够的负责任,也要足够的仔细才行。如其在事后去展现你的仔细,还不如在事前就充分的准备。
一朝被蛇咬,十年怕井绳。在亲身体会到这句话的真谛之前,很多人的状态很类似下面这句话:不进棺材不落泪。
大家都在提不要用全局变量,但很少有人告诉人们为什么。Windows这个环境太优越了, 以至于相当多的人在潜意识里,都有一个想法:用了全局变量也没什么问题。是的,在Windows上,用了全局变量,无论是编译还是运行,似乎都没有什么问题。但是作为一个曾经被蛇咬的人,有义务提醒你,不要用全局变量,因为全局变量不好用,不能用。
全局变量需要运行时库的支持。在执行入口点代码之前,全局变量要要被初始化。普通的全局变量还好说,如果是一个全局的类对象,还涉及构造函数的调用。其实是运行时对于全局变量全局对象的处理是比较复杂的。 想象一下,你去参加一个会议,精心准备你的发言,如果最后被告知会议的议程安排里根本没有让你发言这一过程,恐怕你会失望。全局对象就是这样,有的运行时就没有全局对象初始化这个步骤。那么你的构造函数里的代码永远不会被执行,如果有虚函数,那么情况更复杂,可能连虚函数表也没有被初始化。你失望了还有下一次机会,如果你的代码失望了,唯一的结果就是让你的进程莫名其妙的崩溃。
另外有一些编译环境,可能在语法上就不支持全局变量。
不能用全局变量还有另一个理由。考虑一下,假如有多个互相关联的全局对象,那么你无法控制这些全局对象的构造函数的调用次序,以满足你在逻辑上对他们的期望。
跟全局对象类似,静态成员函数对运行时库也有一些要求,同时也经常会成为被运行时库的实现者们PK掉的地方。在此提醒你,在被蛇咬之前,把蛇搞定。
枚举类型的问题是,枚举类型这个数据类型是善变的。一般来说,它的大小和unsigned short相当,但是有例外。有的编译环境可以把枚举类型当作int处理,还有的编译器根据你在枚举类型里指定的述职的取值范围决定这个枚举类型的存储空间大小。那么就是说,它的大小不再是一个short那么小了。想象一下,如果有人把一个int传给你,而你却当作short来存储,那么有可能为堆栈错乱带来安全隐患。接口中尤其不要用枚举类型.
写到这里,突然想到一句话,聪明反被聪明误。
先看个例子。
Struct S{
Struct {
Int a1;
Int a2;
};
Struct {
Char b1;
Char b2;
};
};
现在看下面的代码。
S s;
s.a1 = 1;
s.a2 = 2;
没问题啊,多简洁,引用内层结构体的成员变量很是方便。
有问题,准确地说,是很多编译器的问题。一些编译环境不支持这样的匿名结构体的用法。
一旦你的代码要移植到这个编译环境上,那么你不得不在整个工程的代码里修改所有这种用法,那时你绝对不会觉得这样的代码有多么的简洁。
工具函数
窃代码不算偷。在实现一些功能时,为追求开发速度,难免要使用一些网上公布的算法或开源的源码,可以理解,它山之石可以攻玉。
但是你有没有想到,你发现的好东西,别人也可以分享,假如有一天,两个分享了同样代码的公司,要合作开发一个项目的时候,会有什么问题。如果大家都是原版照抄,最多在在链接时产生多重符号定义的问题,简单屏蔽任意一方的实现,即可解决问题。最可怕的是,各自都修改了其中一些代码,形成了有公司特色的代码,那就意味着,任何一方的代码都不能屏蔽。只能老老实实的修改这些函数的名称了。
为什么不在一开始就形成有公司特色的函数名称呢?
本文的前导帖子是:<写可移植的C/C++代码>
http://blog.csdn.net/robotom/archive/2007/03/25/1540245.aspx
作者信息
网络ID robotom
Email robotom@sina.com
BLOG http://blog.csdn.net/robotom/
发表于 @ 2007年03月25日 17:03:00|评论(loading...)|编辑