问题描述
|
我对使用
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进行强制转换,但在具有统一指针表示形式的平台上可以省略。