一篇关于intptr_t 和 uintptr_t的文章【英文的】

浪2013 2012-10-11 09:10:16
C99 Core Features in C++0X
Last updated May 6, 2005.

The latest C standard ISO/IEC 9899 (known as C99) introduced quite a few core and library extensions that aren't supported in ISO C++ yet. The C++ standards committee is working with WG14 (the ISO C standards committee) to resolve these incompatibilities. The aim is to adopt C99 features that can be useful or necessary in C++, while rejecting features and library extensions that C+ doesn't need. Here, I present two of these C99 features: long long and intptr_t, and discuss their future in C++.

A long long Story
The C99 long long type and its unsigned counterpart aren't really needed in core C++. Since K&R days, C has always had at least one redundant integral type which is identical to at least one more integral type. In 32-bit systems, int and long are identical; in 16-bit systems, short and int were interchangeable, and so on. Therefore, it was possible to redefine long as a 64-bit integral type in 64-bit systems, while retaining int as a 32-bit integral type in 32/64-bit systems. Indeed, this is exactly what many 64-bit systems have done, including Solaris and Win64.

The main reason for introducing long long into C99 was the C99 <math.h> library. For example, take this minimal pair:

#include <math.h>
long int lrint(double x); //32-bit
long long llrint(double x);//64-bit


If you omit one long from each prototype, a 32-bit platform sees these two functions as having the same return type.

However, long long is incompatible with C++98. If you try to compile a C program that uses long long, you get a compilation error. Look at the following program:

int main()
{
long long x=0LL;
x++;
}


Using Comeau C/C++ 4.3.3, it compiles successfully in C mode. When compiled in strict C++ mode, you get a compilation error:

Line 3: error: the type "long long" is nonstandard,
Consideration: Use --long_long for this to work in strict mode
long long x=0LL;
^


The proposed recommendation to use long_long is problematic because other compilers don't recognize this token. Furthermore, if you fix the code as recommended and compile it once more as a C program, you're in trouble again:

int main()
{
long_long x=0LL; //compiled in C mode
x++;
}
"ComeauTest.c", line 3: error: identifier "long_long" is undefined
long_long x=0LL;
^


This is a serious compatibility issue, especially for programmers who use both C++ and C99. The only workaround, at present, is conditional compilation. To solve this problem, the C++ standards committee has decided to add long long as well as their corresponding LL and ULL affixes to C++.

intptr_t and uintptr_t
The C99 header <inttypes.h> declares sets of typedefs for portable integral types, such as fastest minimum-width integer types. For example:

int_fast8_t int_fast16_t int_fast32_t int_fast64_t

exact-width signed integer types such as:

int8_t int16_t int32_t int64_t

And more. In addition, this header also declares the following typedef name:

intptr_t
Any valid pointer to an object (the original C99 text speaks of "any valid pointer to void") can be converted to this type, and then converted back safely to void *. The result must compare equal to the original pointer. In other words, intptr_t legalizes a popular yet non-portable tradition of converting data pointers to integral types, and vice versa. The POSIX API defines several functions that rely on such conversions; similarly, Windows frameworks often store the this pointer as an integer. C++0x will support intptr_t, too.

The introduction of intptr_t is chiefly important in 64-bit computing. The problem is that most 64-bit systems use the LP64 model, whereby long and data pointers have the same size of 64-bits, whereas int has only 32-bits. If you want to write dually-targeted code for 32/64-bit platforms, intptr_t is guaranteed to work correctly on both.

uintptr_t is the unsigned counterpart of this typedef.

intptr_t and GC
Interestingly, intptr_t has recently drawn the standards committee's attention with reference to a standard garbage collector (GC). A typical GC keeps track of pointers in the program, ensuring that the memory to which they point is released when they are no longer referenced in the program. In simples cases such as

void f()
{
S * ptr = new S;
}//ptr's memory can now be collected


The GC can easily recognize that ptr cannot be referenced after f() returns, so it knows that the memory to which ptr points can be reclaimed. However, if you use an intptr_t variable to disguise a pointer, the GC might not recognize that the object to which ptr is bound is still referenced outside f():

void f(intptr_t & alias)
{
S * ptr = new S;
alias=(intptr_t)ptr;
}


The caller can still access the dynamically allocated object through the disguised pointer alias. The GC can't know that; after all, alias might be used as an ordinary integer, too. If the GC decides to reclaim the memory of ptr after f() returns, the caller might still access it via alias. This is just as bad as accessing an object to a pointer after deleting it. By contrast, if the GC decides to mark ptr's value as referenced (i.e., its memory shouldn't be reclaimed), this program might cause a memory leak.

That said, intptr_t is here to stay. It was introduced to permit commonplace C programming practices. C++ will have to follow suit. GC challenges notwithstanding, intptr_t is one of the smallest problems that any standard C++ GC will have to deal with.


http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=223
...全文
327 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
漫步者、 2012-12-10
  • 打赏
  • 举报
回复
javamy035 2012-12-09
  • 打赏
  • 举报
回复
我只是来围观一下!!

64,676

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧