http://blog.csdn.net/cs_zhanyb/article/details/16973379
http://blog.csdn.net/justlinux2010/article/details/7490420
http://blog.nklike.com/integer-in-nginx.html 道出了真相
最近开始研读Nginx的源代码,首先就遇到如下的代码:
- typedef intptr_t ngx_int_t;
- typedef uintptr_t ngx_uint_t;
intptr_t和uintptr_t是什么类型?以前没见过,于是查了一下。
这两个数据类型是ISO C99定义的,具体代码在linux平台的/usr/include/stdint.h头文件中。
该头文件中定义intptr_t和uintptr_t这两个数据类型的代码片段如下:
- /* Types for `void *' pointers. */
- #if __WORDSIZE == 64
- # ifndef __intptr_t_defined
- typedef long int intptr_t;
- # define __intptr_t_defined
- # endif
- typedef unsigned long int uintptr_t;
- #else
- # ifndef __intptr_t_defined
- typedef int intptr_t;
- # define __intptr_t_defined
- # endif
- typedef unsigned int uintptr_t;
- #endif
在64位的机器上,intptr_t和uintptr_t分别是long int、unsigned long int的别名;在32位的机器上,intptr_t和uintptr_t分别是int、unsigned int的别名。
那么为什么要用typedef定义新的别名呢?我想主要是为了提高程序的可移植性(在32位和64位的机器上)。很明显,上述代码会根据宿主机器的位数为intptr_t和uintptr_t适配相应的数据类型。
另外,如注释所言,定义这两个数据类型别名也是为了“void *”指针。
在C语言中,任何类型的指针都可以转换为void *类型,并且在将它转换回原来的类型时不会丢失信息。
==================================
很明显intptr_t不是指针类型,但是上边的一句注释(/* Types for `void *' pointers. */)让人很疑惑。既然不是指针类型,但是为什么说类型是为了“void *”指针?
又查了一下在《深入分析Linux内核源码》中找到了答案,原文描述如下:
尽管在混合不同数据类型时你必须小心, 有时有很好的理由这样做. 一种情况是因为内存存取, 与内核相关时是特殊的. 概念上, 尽管地址是指针, 内存管理常常使用一个无符号的整数类型更好地完成; 内核对待物理内存如同一个大数组, 并且内存地址只是一个数组索引. 进一步地, 一个指针容易解引用; 当直接处理内存存取时, 你几乎从不想以这种方式解引用. 使用一个整数类型避免了这种解引用, 因此避免了 bug. 因此, 内核中通常的内存地址常常是 unsigned long, 利用了指针和长整型一直是相同大小的这个事实, 至少在 Linux 目前支持的所有平台上.
因为其所值的原因, C99 标准定义了 intptr_t 和 uintptr_t 类型给一个可以持有一个指针值的整型变量. 但是, 这些类型几乎没在 2.6 内核中使用。
=============
可以看到注释是: Types for `void *’ pointers. 那么这是什么含义呢?
我们知道所谓的指针,其实是内存的地址,而内容是该地址内存中实际存储的数据。void *是指无类型指针,当需要进行转化时,这个类型可以被安全的在 void * 和整数间转换,而不会出现由于指针和整型的字宽不同导致的问题。
C语言中,指针和整数之间的转换经常用到(多用于需要精确控制数据在内存中的精确布局时),在32位平台上,由于指针类型的字宽和int相同,所以我们不太在意这个问题。但是到了 64 位平台上,由于目前几乎所有64位系统都采用LP64模型,既整数依旧是32位,而指针是64位的。intptr_t 这个数据类型就成了安全跨平台编程的保证。也就是说,当你需要把指针作为一个整数来运算时,转换成 intptr_t才是安全的,可以在运算完毕安全的转回指针类型。
在64位机器上:
cout << "sizeof void*" << sizeof(void*) << endl;
cout << "sizeof int " << sizeof(int) << endl;
cout << "sizeof long int " << sizeof(long int) << endl;
cout << "sizeof int*" << sizeof(int*) << endl;
结果:
sizeof void*: 8
sizeof int: 4
sizeof long int: 8
sizeof int*: 8
http://blog.csdn.net/luotuo44/article/details/38780157
ntptr_t是一个很重要的类型,特别是在64位系统中。如果你要对两个指针进行运算,最好是先将这两个指针转换成intptr_t类型,然后才进行运算。因为在一些64位系统中,int还是32位,而指针类型为64位,所以两个指针相减,其结果对于32位的int来说,可能会溢出。