为什么/何时使用`intptr_t`在C中进行types转换?

我有一个关于使用intptr_tlong int 。 我发现增加内存地址(例如通过手动指针算术)因数据types而异。 例如增加一个字符指针增加1的内存地址,而增加一个int指针增加4,8为双,16为长双等…

起初,我做了这样的事情:

 char myChar, *pChar; float myFloat, *pFloat; pChar = &myChar; pFloat = &myFloat; printf( "pChar: %d\n", ( int )pChar ); printf( "pFloat: %d\n", ( int )pFloat ); pChar++; pFloat++; printf( "and then after incrementing,:\n\n" ); printf( "pChar: %d\n", (int)pChar ); printf( "pFloat: %d\n", (int)pFloat ); 

它编译和执行得很好,但XCode给我警告我的types转换:“从指针转换为不同大小的整数”。

经过一些谷歌search和结果(后者是一个字吗?),我看到一些人推荐使用intptr_t

 #include <stdint.h> 

 printf( "pChar: %ld\n", ( intptr_t )pChar ); printf( "pFloat: %ld\n", ( intptr_t )pFloat ); 

这确实解决了错误。 所以,我想,从现在开始,我应该使用intptr_t来进行types转换指针…但是后来发现我可以通过用intreplaceint来解决问题:

 printf( "pChar: %ld\n", ( long int )pChar ); printf( "pFloat: %ld\n", ( long int )pFloat ); 

所以我的问题是,为什么intptr_t有用,它应该什么时候使用? 在这种情况下,这似乎是多余的。 很显然, myCharmyFloat的内存地址太大,无法放入int …所以将它们typesmyFloat long int解决这个问题。

是否有时内存地址太长,以至于long int ? 现在我想起来了,如果你有大于4GB的内存,那么内存地址可能会超过2 ^ 32 – 1(无符号长整型的最大值…),但是C之前就已经创build了可以想象的吧? 还是他们有先见之明?

谢谢!

这是事情:在一些平台上, int是正确的大小,但在其他平台上, long是正确的大小。 你怎么知道你应该使用哪一个? 你没有。 有人可能是对的,但标准不能保证它会是哪一个(如果是的话)。 所以标准提供了一个被定义为正确大小的types,不pipe你在哪个平台上。 之前你必须写:

 #ifdef PLATFORM_A typedef long intptr; #else typedef int intptr; #endif 

现在你只写:

 #include <stdint.h> 

它涵盖了更多的情况。 想象一下专门为您的代码运行的每个平台上面的代码片段。

intptr_t是一个新的发明,创造了64位甚至128位内存地址后想象。

如果您需要将指针转换为整数types,则始终使用intptr_t 。 做任何事情都会给将来需要移植代码的人带来不必要的问题。

在Mozilla / Firefox这样的程序中,当人们想要在64位Linux上进行编译时,需要很长时间才能解决所有这些问题。

首先, intptr_t仅用于数据指针(不是函数),并不保证存在。

那么,不,你不应该用它来打印的目的。 %p是为了这个。 你只需要把你的指针指向(void*)然后就可以了。

算术/访问单个字节也是不好的。 转换为(unsigned char*)

intptr_t是真正的罕见场合,你必须将指针解释为整数(它们实际上不是)。 不,如果你不这样做。

你可以通过使用p转换说明符让你的生活更轻松:

 printf("%p\n", (void *)foo); 

另外,打印type (u)intptr_tvariables的可移植方法是使用inttypes.hPRI*PTRmacros; 以下相当于在我的平台(32位)上使用p

 printf("%08" PRIxPTR "\n", (uintptr_t)(void *)foo); 

为了完全的可移植性,对void *进行强制转换是必要的,但是在具有统一指针表示的平台上可以省略。