如果我知道数据对象的地址,我可以将地址存储为整数并将整数作为指针运行吗?
例如,
void main(){
long a = 101010;
long *p = &a;
long b = p;
printf("%lld\n", *(long*)b);
}
它总是安全吗?
评论:long b = p;
会发出警告:
Initialization makes integer from pointer without a cast
但是,该程序会打印101010
。
答案 0 :(得分:7)
标准并不保证这样的演员阵容总能奏效。
要将指针存储在整数类型中,请使用intptr_t
(或其未签名的表兄uintptr_t
)。保证将void *
指针转换为此类型并转换回来,从而产生相同的值。
请注意,这些类型是可选的。
答案 1 :(得分:1)
sizeof(long)
通常由编译器定义(受底层硬件架构影响)。
sizeof(long*)
会受到平台上虚拟内存地址空间的影响。
例如,使用适用于64位操作系统的Visual Studio编译器和基于x64的处理器:
sizeof(long) == 4
sizeof(long*) == 8
因此:
long b = p
,只有p
的4个最不重要字节被复制到b
*(long*)b
,您可能尝试访问无效的内存地址在此示例中,如果p
的4个最重要字节为零,则“不会造成伤害”。但由于不能保证是这种情况,因此sizeof(long) != sizeof(long*)
此代码通常不安全。
除此之外,即使sizeof(long) == sizeof(long*)
,您仍应避免使用此类转换(指向整数的指针),以便将代码移植到其他平台。
<强>更新强>
请注意,printf("%lld\n", *(long*)b)
也不安全。
您基本上应该"%ld"
用于long
值,"%lld"
用于long long
值。
如果sizeof(long) < sizeof(long long)
,则可能会在运行时导致内存访问冲突。
答案 2 :(得分:0)
要在安全方面,我们应该认为不安全。
n
位系统上指针的大小为n
位。例如,在任何64位体系结构/编译器上,指针的大小应为8字节。这是保证。
但是,数据类型没有这样的保证。它依赖于编译器。在你的情况下,两者恰好都具有相同的大小,这就是它起作用的原因。
编辑:
警告
Initialization makes integer from pointer without a cast
您的编译器非常适合生成警告。请检查数据类型。 int *
变量不等于int
变量。在您的情况下,它的工作原理只是因为您的特定情况/实现中的长度相同。
答案 3 :(得分:0)
即使p
值和b
值相同,也只有p
可以访问a
,即可以指向a
,b
不能指向a
。因为p
被声明为指针。 b
被声明为变量。
您无法通过a
访问b
。那么你的问题是怎么合适的。在b
中,a
的地址仅被视为value
而不是address
,因为b
变量不是指针..
即使它打印101010
,该程序也不是通用的。
答案 4 :(得分:-1)
指针是一个变量,其值是另一个变量的地址。与任何变量或常量一样,您必须先声明指针才能使用它。指针变量声明的一般形式是:
type *var-name;
所有指针的值的实际数据类型,无论是整数,浮点数,字符还是其他,都是相同的,是表示内存地址的长十六进制数。不同数据类型的指针之间的唯一区别是指针所指向的变量或常量的数据类型。
指针通常具有固定大小,例如。在32位可执行文件上,它们通常是32位的。有一些例外,比如旧的16位窗口,当你必须区分32位指针和16位......通常可以非常安全地假设它们在一个内部是统一的在现代桌面操作系统上给出了可执行文件。