« 新年快乐 | 返回首页 | 想找个朋友 »

C 语言(C99) 对 64 位整数类型的支持

前几天跟同事闲聊 64 位操作系统时,有人问起 64 位平台上,C 语言的数据类型如何确定的问题。以及跨平台(跨 16 位、32 位和 64 位平台)程序如何选用合适的数据类型。

我查了一下资料,记录如下:

char 通常被定义成 8 位宽。

int 通常被定义成 16 位或 32 位宽(或更高),它取决于平台。编译器将在这两者间选择最合适的字宽。

short 通常被定义成 16 位宽。

long 通常被定义成 32 位宽。

C99 为 C 语言扩展了新的整数类型 long long ,通常被定义成 64 位宽。(GNU C 亦支持)

但是 C 标准并没有定义具体的整数类型的宽度,只定义了 long long 的级别高于 long ,long 的级别高于 int ,int 的级别高于 short ,short 的级别高于 char 。(另外有 _Bool 永远是最低级别)。级别高的整数类型的宽度大于等于级别较低的整数类型。

char 的宽度用宏 CHAR_BIT 定义出来,通常为 8 ,而除了位域类型外,其它所有类型的位宽都必须是它的整数倍。

如果需要精确确定整数类型的宽度,在 C99 以及 GNU C 中,需要包含 stdint.h ,使用其中几种扩展的整数类型。

int16_t 可以保证整数长度为精确的 16 位。同样,int8_t 可以保证整数长度为精确的 8 位。类似的还有 int32_t int64_t 以及无符号类型 uint8_t 等等。

int_least16_t 可以得到一个当前平台所支持的至少有 16 位宽的最短整数类型。(其它同类型的可以类推)

int_fast32_t 可以得到当前平台下得到处理速度最快的至少为 32 位的整数类型。

intmax_t 可以获得当前平台所支持的最大宽度的整数类型。

在书写整数常数时,在数字后加上 L 表示是一个 long 类型的整数,加上 U 表示是一个 unsigned 整数,加上 LL 表示是一个 long long 类型整数。但是由于 long long 这些并不能确定准确字宽,有此需求时,可以借助宏 INTn_C(value) 来转换。例如,想指定一个 64 位整数常数 0x1234 ,可以写成 INT64_C(0x1234) 。若在当前平台上 int_least64_t 就是 long long int 的话,这个宏会被展开成 0x1234LL 。

最后再提一个很重要的扩展类型:intptr_t (无符号版本写成 uintptr_t)这个类型可以被安全的在 void * 和 整数间转换,对于写跨 64 位平台的程序非常重要。也就是说,当你需要把指针作为一个整数来运算时,转换成 intptr_t 才是安全的,可以在运算完毕安全的转回指针类型。

C 语言中,指针和整数之间的转换经常用到(多用于需要精确控制数据在内存中的精确布局时),在 32 位平台上,由于指针类型的字宽和 int 相同,所以我们不太在意这个问题。但是到了 64 位平台上,由于目前几乎所有 64 位系统都采用 LP64 模型,既整数依旧是 32 位,而指针是 64 位的。intptr_t 这个数据类型就成了安全跨平台编程的保证。

最后,附上 C99 标准文档技术修正第三版 ISO/IEC 9899:TC3

Comments

看来涉及到跨平台的开发时,就得仔细掂量掂量所用到的 Type 了啊(思考者状

C1x的一个原则挺好玩的:
12. Trust the programmer, as a goal, is outdated in respect to the security and safety programming communities. While it should not be totally disregarded as a facet of the spirit of C, the C1Xversion of the C Standard should take into account that programmers need the ability to check their work.

后面的回帖也很有趣,有人就是认为实在没必要再折腾C了,因为C++也可以拿来写C代码嘛

原文见:
http://blogs.msdn.com/vcblog/archive/2007/11/05/iso-c-standard-update.aspx

当你需要把指针作为一个整数来运算时,转换成 intptr_t 才是安全的,可以在运算完毕安全的转回指针类型。
----------------------
虽然每次看到、写到这样的代码心理都会一怵、但似乎又已经有些麻木了-_-!
好在我们的程序,暂时不会有跨到64位机上的要求。

前一阵还考虑过64位下指针与整数转换的问题,原来有intptr_t

今天重新读了一遍 C 的标准文档,发现标准中并不定义 int long short 这些的具体宽度。只定义了类型级别。

我昨天翻的书(The Complete Reference C 第4版)过时了。

另楼下的说法和资料也些须修正之处:

1. long long 现在已经被标准化,但并无规定其宽度。

2. 标准并不限制 short / int / long 这些至少有多少位宽,

C的数据类型现在好别扭啊,long long,写程序看着都不爽,幸亏偶只用Java:)

“long 无论在任何平台上都是 32 位宽。”
这句话不对吧。

如果是LP64模型(如Linux和*BSD),long 是64-bit。

如果是LLP64模型(如Windows),long 是 32-bit;新增long long类型,为64-bit。

http://www.unix.org/version2/whatsnew/lp64_wp.html

有一点不同意
short和long的长度,我记得标准中只规定,short不会低于16位,long不会低于32位,除此之外对其精度没有限制。
一般int是这个平台的自然长度。

Post a comment

非这个主题相关的留言请到:留言本