32 位/64 位兼容代码规范(待完善)

C++是一个强类型的语言,在编码的过程中,一定要时刻注意到你操作对象的类型

很多类型不一致的隐式赋值,不仅仅造成了我们的代码很难跨平台,还可能是导致莫名奇妙bug的隐患。

如果确实需要类型的转换,请显式的转换数据类型, static_cast等等。

当前我们在Solaris下面使用的forteC6.2编译器,这个编译器本身是一个比较老的编译器,很多C++规范支持都不够好,在加上Solaris操作系统特殊的内存使用机制,让我们养成了一些写代码的不规范的习惯。

 

forteC6.2编译器可以编译通过的代码不意味着代码是标准的。

Solaris操作系统上面运行正常的代码不意味着代码是正确的。

 

多想一下,多在其他平台上面编译一下,对我们代码的正确性、可靠性、可移植性,以及我们的技能都会有莫大的提高。

 

注:

本版规范是初次版本,后续会添加修正后再次发布,欢迎大家提出更有效的问题解决办法或者编码规范。有什么问题请反馈给我(庄乾锋 61576),谢谢

 

版本信息:2008-6-30

1      pragma pack 问题

不兼容代码:

#pragma pack(1)

...

#pragma pack(4)

 

可能导致的问题:

1.         是没有可移植性,

2.         是不能确保在嵌套的环境下也能正常使用。

3.         64 位平台上,会产生 core dump

 

修改方法:

IA64的平台上面,使用宏开关SUSE_IA64分隔。在C++中如果无特殊需要,建议不要操作二进制字节流,不要对pragma pack,直接使用对应的对象操作即可。

#ifdef SUSE_IA64

#pragma pack(push,1)

#else

#pragma pack(1)

#endif

...<define your struct here>

 

#ifdef SUSE_IA64

#pragma pack(pop)

#else

#pragma pack(4)                ----此处的代码写的非常槽糕,如果想恢复原来,使用pragma pack(pop)

#endif

2      用平台无关类型替换特定类型

(a)指针类型

不兼容代码:

#ifdef SUSE_IA64

  switch (reinterpret_cast<long>(pvArg))

#else

  switch (reinterpret_cast<int>(pvArg))

#endif

可能导致的问题:

指针长度在 32 位机器上使 32 位的,而在 64 位机器上是64 位的,使用

int和 long 强制转换容易出错,且不具备可移植性,建议使用intptr_t和uintptr_t(unsigned)。

修改方法:

switch (reinterpret_cast<intptr_t>(pvArg))

(b)使用STL内置数据类型

STL内置数据类型string::size_type 替换int/long

错误代码:

string fdn = “www.sina.com”;

unsigned int pos = fdn.rfind('.');

可能导致的问题:

rfind 的函数原型是:

string::size_type

      rfind(const basic_string& __str, size_type __pos = npos) const

使用上述代码导致了隐式的类型转换,可能导致数据丢失。

修改方法:

string::size_type pos = fdn.rfind('.');

(c) 使用系统定义类型

错误代码:

long localTime = 0;

可能导致的问题:

在某些情况下,如指针,时间等需要随系统的迁移而改变变量的长度的。可以采用系统定义的一些类型。如果使用 int 类型,在 32 位和 64 位系统中都是 32 位的,不具备可移植性。常用类型见下表。

Type

Purpose

clock_t

Represents the system times in clock ticks.

dev_t

Used for device numbers.

off_t

Used for file sizes and offsets.

ptrdiff_t

The signed integral type for the result of subtracting two pointers.

size_t

The size, int bytes, of objects in memory.

ssize_t

Used by functins that return a count of bytes or an error indication

time_t

Used for time in seconds.

 

修改方法:

#include <sys/types.h>

time_t localTime = 0;

(d)用 int32_t 类型统一变量宽度

不兼容代码

32位版本为long, 64位版本为int, 统一修改为int32_t/uint32_t (unsigned)

#ifdef SUSE_IA64

  const unsigned int _neObjId,

#else

  const unsigned long _neObjId,

#endif

可能导致的问题:

在 LP64 模型中(目前我们的 64 位机器就使用这个模型)。long 是 64 位的,而在 ILP32 位系统中,long 是 32 位的。在 C99 标准中定义了这几个新的统一长度的类型: int8_t, int16_t, int32_t, int64_t 等。

 

修改方法:

  #include <inttypes>

  const uint32_t _neObjId,

(e)通讯协议相关类型

通讯协议相关的, 考虑与原系统兼容性, 必须保持原来的32位通信协议栈。

32位版本中的long全部修改为int32_t

不兼容代码

#ifdef SUSE_IA64

  /* [Keyword] */

  int     MOCId;

  int     MOIIdLength

  int     measTypesLength;

#else

  long     MOCId;

  long     MOIIdLength

  long     measTypesLength;

#endif

修改方法:

  #include <inttypes>

  int32_t     MOCId;

  int32_t     MOIIdLength

  int32_t     measTypesLength;

(a)CORBA相关数据类型

CORBA交互时尽量使用CORBA定义的数据类型。比如CORBA::Ulong在64位上仍然是32位。下面是对照表,左侧是IDL数据类型,右侧是TAO对应数据类型:

 

boolean        

CORBA::Boolean

char           

CORBA::Char

octet          

CORBA::Octet

short          

CORBA::Short

Unsigned short 

CORBA::UShort

long           

CORBA::Long

Unsigned long  

CORBA::ULong

long long      

CORBA::LongLong

Unsigned long long      

CORBA::ULongLong

wchar          

CORBA::WChar

float          

CORBA::Float

double         

CORBA::Double

long double    

CORBA::LongDouble

 

不兼容代码

#ifdef SUSE_IA64   

    CORBA::ULong k=0;

#else

    long k=0;

#endif  

修改方法:

CORBA::ULong k=0;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值