为什么/何时在C语言中使用`intptr_t`进行类型转换?

问题描述

| 我对使用
intptr_t
long int
有疑问。我观察到递增的内存地址(例如通过手动指针算术)因数据类型而异。例如,递增char指针会将内存地址加1,而递增int指针会将double值加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对我的类型转换发出警告:\“从指针到不同大小的整数的广播。” 经过一番谷歌搜索和binging(后者是一个词吗?)之后,我看到有人建议使用
intptr_t
#include <stdint.h>
...
printf( \"pChar:  %ld\\n\",( intptr_t )pChar );
printf( \"pFloat: %ld\\n\",( intptr_t )pFloat );
确实解决错误。因此,我认为从现在开始,我应该使用
intptr_t
进行类型转换指针...但是经过一番烦躁之后,我发现我可以通过将
int
替换为
long int
解决问题:
printf( \"pChar:  %ld\\n\",( long int )pChar );
printf( \"pFloat: %ld\\n\",( long int )pFloat );
所以我的问题是,为什么“ 0”有用,何时使用?在这种情况下,似乎是多余的。显然,
myChar
和ѭ12the的内存地址太大而无法容纳
int
...因此将它们类型转换为
long int
解决了这个问题。 有时内存地址对于ѭ1来说也太大了吗?现在,我考虑了一下,我想如果您有> 4GB的RAM,这是可能的,在这种情况下,内存地址可能会超过2 ^ 32-1(无符号长整数的最大值...),但是C创建的时间很长在那之前是可以想象的,对吧?还是他们有先见之明? 谢谢!     

解决方法

        这就是问题:在某些平台上,
int
是正确的尺寸,但在其他平台上,
long
是正确的尺寸。您如何知道应该使用哪一个?你不知道一个可能是正确的,但是该标准不能保证它将是哪个(如果是)。因此,无论您使用的是哪种平台,该标准都提供了一种定义为正确大小的类型。在您必须写之前:
#ifdef PLATFORM_A
  typedef long intptr;
#else
  typedef int intptr;
#endif
现在,您只需编写:
#include <stdint.h>
它涵盖了更多案例。想象一下,将上面的代码片段专门用于代码在其上运行的每个平台。     ,        “ 0”是一项新发明,是在设想了64位甚至128位内存地址之后创建的。 如果需要将指针转换为整数类型,请始终使用
intptr_t
。对于将来需要移植代码的人,做任何其他事情都会引起不必要的问题。 当人们想在64位Linux上编译该程序时,花了很长时间才解决了诸如Mozilla / Firefox这样的程序中的所有错误。     ,        首先,“ 0”仅用于数据指针(不用于函数),不能保证存在。 然后,不,您不应将其用于打印目的。
%p
是为此目的。您只需要将指针投射到
(void*)
即可。 对算术/访问单个字节也没有好处。改为改为
(unsigned char*)
intptr_t
实际上是非常罕见的情况,您必须将指针解释为整数(它们实际上不是整数)。如果不是,那就不要。     ,        您可以使用
p
转换说明符来简化生活:
printf(\"%p\\n\",(void *)foo);
同样,打印
(u)intptr_t
类型变量的可移植方式是使用
inttypes.h
中的
PRI*PTR
宏。以下等效于在我的平台(32位)上使用
p
printf(\"%08\" PRIxPTR \"\\n\",(uintptr_t)(void *)foo);
完全移植需要对34进行强制转换,但在具有统一指针表示形式的平台上可以省略。