好久没有写东西了,先写一点,以后再扩充.
1.使用平台编译器预定义的宏.
比如在windows下,有这样一个宏WIN32.或者_WIN32.
linux下有__linux__等等.
比如OGRE的OgrePlatform.h中的定义:
#if defined( __WIN32__ ) || defined( _WIN32 )
# define OGRE_PLATFORM OGRE_PLATFORM_WIN32
#elif defined( __APPLE_CC__)
# define OGRE_PLATFORM OGRE_PLATFORM_APPLE
#else
# define OGRE_PLATFORM OGRE_PLATFORM_LINUX
#endif
在OGRE下,可以使用这个宏来判断编译平台.如:
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#pragma warning(disable:4995)
#endif
这样,即使是在不同的平台下,如果有类似功能的API可以使用,而他们的名字不同,就可以使用宏来进行条件编译了.
2.尽量使用标准库函数.上面的方法,不到万不得已,还是不要用的好,如果CRT的功能可以实现,就尽量使用C标准库.这样做的好处就是,使得代码便于移植,因为没有用到平台相关的API.
举个例子,Win32下有MultiByteToWideChar函数可以实现 多字符/宽字符的转换,
而C标准库中stdlib.h提供了mbstowcs函数可以类似的实现这个功能.如果你的程序要考虑平台因素的话,尽量使用标准库函数.类似的很多了,比如比较明显的ExitProcess(Win32 API)和exit(CRT),
以及CreateThread(Win32 API)和_beginthread(CRT)
其实标准库函数很多时候是对平台相关API的封装,就像一个中间层一样,使得上层代码比较统一.
3.尽量使用标准类型.比如标准的uintptr_t/intptr_t 类型,是一个整型的指针类型.win32也有UINT_PTR和INT_PTR.但是如果考虑平台因素的话,当然使用前者比较好了,linux下可没有UINT_PTR这样的类型,当然,除非你想自己定义.个人认为,现有的标准如果能用的话,还是尽量去用吧.
使用intptr_t 代替int的另一个好处,当然就是32-64位平台的移植了.不多说了.
另一个办法就是,自己定义一套类型,在程序中自己使用.举个例子:
//8bit int
typedef char int8, *pint8;
typedef unsigned char uint8, *puint8;
//16bit int
typedef short int16, *pint16;
typedef unsigned short uint16, *puint16;
//32bit int
typedef long int32, *pint32;
typedef unsigned long uint32, *puint32;
//64bit int
typedef long long int64, *pint64;
typedef
unsigned long long uint64, *puint64;
//32,64bit floating point
typedef float fp32, *pfp32;
typedef double fp64, *pfp64;
//wchar_t
typedef wchar_t wchar, *pwchar;
//tchar
typedef TCHAR tchar, *ptchar;
这样的类型可能在结构的成员声明中使用的时候会比较清晰.
4.使用Unicode.unicode使得语言处理比较统一.需要注意的地方是,不同平台使用的编码是不一样的.
例如win32使用的是16位的UCS16,sizeof(wchar_t) = 2,
而linux用的是UCS32编码,sizeof(wchar_t) = 4.
在做编码转换的时候,比如要将UTF转换为wchar_t(UCS),那么还是不得不考虑平台因素了.
使用UTF编码是个不错的注意,例如CEGUI就支持UTF8和UCS32.Ogre现在也支持UTF8和宽字符了.
但是很多时候还是需要额外的转换.特别是字符串常量在源文件中定义的时候.解决的办法就是把所有用到的字符串都保存在外部的文本文件里.
暂时先到这里.
作者:萧の十三郎 @ 百度
以后有时间了说说大小端方式,还有编译器相关的兼容处理.