现在的位置: 首页 > 综合 > 正文

规范化的C++编程方法备忘录 整数声明

2013年08月11日 ⁄ 综合 ⁄ 共 2232字 ⁄ 字号 评论关闭

形式上把整数分成3大类:

-通用型整数:int/long/short/char,及他们的unsigned类型

特点:标准字节的宽度 | 用于大小有限,又不强调最大值,或者最大值总保证满足实际需要的场合。
| 平台无关。不同的编译器,同样类型的整数,不同编译器厂商规定的实际字节的宽度可能不同,具体由编译器厂商决定。
| 不要假定某个类型的具体位宽(除了char/unsigned char),不要假定最大值的具体数值。例如,不要以为int就是32位(尽管现在事实如此)。

-固定位宽:INT8/INT16/INT32/INT64; BYTE/WORD/DWORD/UINT64注意有些编译系统的库只有第一个字母大写,或者全部小写。

特点:指定字节宽度 | 用于强调固定宽度的场合。
| 编译器无关。平台无关 | 意义很明确:例如DWORD就是4字节。

 

-指针型整数:size_t/diffmem_t/intptr_t/uintptr_t

特点:宽度等于指针宽度 | 常用于取得指针的比较结果、指针取值、通用混合类型变量的传递(VC.NET之前版本不支持)。
| 编译器无关。平台相关 | 不要假定具体位宽,不要假定最大值的具体数值。例如,不要以为size_t等于int位宽(尽管win32中如此)。

 

分类的目的:防止出现位兼容性问题;方便编译系统间、硬件平台间移植(如x86到x64)。

说明:

-对于编译器及硬件来说只有一种类型:固定位宽。但这不妨碍我们分类。事实上开发人员面对的首先是类型库而不是编译器。一个完善的编译器应当给出完善的3种类型,而不是让程序员自己写平台转换代码。规范的代码应当没有移植性问题,这包括向一个假设的编译系统和硬件。应当确保最多只需重新编译而不用修改源代码。

-指针型整数不是指针而是整数。

-如果我们看到编译系统的头文件有如下声明:

不表示你也可以这样做。你买一把锁没有自己做钥匙的义务。

对于一些老程序员,很多规则显得比较“新”而且怪异。不过幸运的是,“软件牛仔的时代已经一去不复返了(对于某些人来说,也许是不幸的)”

规则:

A.以下不等式恒成立:

由以上可得出:

1 得到 sizeof(int) >= 2

1、4 得到 sizeof(void *) >= 2

  注意这些公式给正确进行强制类型转换的提示。要把不等式看成真正的不等式,不然你的代码在不同硬件平台间移植时很可能会出问题(例如从win32移植到win64)。如果你的软件代码量很大,你的麻烦就大了。

  有时候正规化的编译器厂商也会自己提供一些自定义整数类型。例如微软的DWORD_PTR保证在任意情况下都可同时容纳一个DWORD或者一个指针型整数。所以不要写了这么久还不明白为什么厂商要定义这么多不同名的“其实是一回事”的整数类型。

B.无符号整数的赋值规范:

-窄类型可安全地赋值给宽类型

-宽类型赋值给窄类型需要强制类型转换,而安全复制的前提是:你已经在原来的宽类型中证明了该转换的值的适用性。

-不同大类间赋值总是需要强制类型转换(除非满足3/4/推论),且安全复制的前提是:如果某较宽整数按照你的实际应用要求(注意这种要求不应该依赖于平台)的取值范围恒包含于较窄目标整数的取值范围,则赋值可行,但必须进行强制类型转换。

 

注意特殊情况的运用。例如下面是有问题的代码:
int a;
LPCTSTR pc = "1", pd = "2";

a = pd - pc // Here. the 'a' should be a size_t typed integer.

但下面的代码却可以:
int b = (int)sizeof(LARG_INTEGER); // That is right because the LARG_INTEGER always takes 8 bytes, which is small and will not be extended in future. 

----------------------------

附议:

1. vc6时代及linux的程序员总有个不好的坏习惯:总是在int和指针间转换来转换去。总是认为指针是32位的。
 - Win32SDK句柄的类型绝大部分为指针类型,少部分为指针型整数,极少部分为通用型整数。如果你有将通用型整数传递指针的例子、习惯,还是改改吧。另外建议还在使用VC6的同志们:如果软件自身的源代码类化的不彻底,还是赶快把VC6扔进垃圾桶吧...
 - 如果你的软件用文件API传递内容于内存中(如用ReadFile/WriteFile),如果是动态的、不定长的块,好好检查源代码(注意DWORD/ULONGLONG与size_t的转化问题,不要懒得去考虑,或者“特殊情况”一番)。

抱歉!评论已关闭.