如何将C指针的物理地址作为值?

问题描述 投票:0回答:2

在我的系统中,

sizeof(void*) = 8 bytes

所有指针类型的大小为8个字节。

我有这个结构

struct element{void* value};

所以这个结构是一个8字节的指针值。

因为所有类型的指针都有8个字节,所以我应该能够将任何类型的变量的物理地址分配给这个void *值

也,

sizeof(double) = 8 bytes;

问题是如何获取任何指针的物理地址作为double值,然后将此值分配给任何其他8字节指针。

所以说,

int i;
int *p = &i;
struct element e;
double phy_address = ?? // the 8 byte value of p (when we print it as %d)

/*now copy this 8 byte phy_address to 8 byte void pointer e.value. */

是否可以将其类型转换为int *或任何其他指针类型?它的地址是......

c pointers
2个回答
1
投票

在大多数系统中,存在与void *大小相同的整数类型。通常这种类型是intlong intlong long int。大多数编译器将提供类型,intptr_t(和它的unsigned cousin uintptr_t),这是这些类型之一的typedef。我认为人们更喜欢使用uintptr_t,因为负地址值通常没有意义。无论如何你应该使用这种类型而不是double。

请记住,uintptr_t只是常规整数类型之一,因此一旦将指针值转换为此类型的变量,就可以执行任何您喜欢的整数运算。至于如何将指针值转换为uintptr_t,请参阅此问题/答案,Converting a non-`void` pointer to `uintptr_t` and vice-versa


0
投票

我使用=这些值可以用作表中的唯一标识符。

好。此信息是必要的,因为不可能将指针转换为具有任何有意义值的浮点数;浮点数将以任何方式具有无意义的价值。

将指针转换为(无意义的)浮点值有两种可能性,但在两种情况下都不能保证两个浮点数对于两个不同的指针是唯一的!

可能性1:

将指针转换为整数,将整数转换为浮点数:

phy_address = (double)(uintptr_t)p;

然而,正如风向标在他的评论中已经提到的那样,double值的精确度有限。

整数值(地址)1234567890123456780和1234567890123456790都将四舍五入为1234567890123456768.0。

可能性2:

因为double和指针都是64位宽,所以你可以生成一个与指针具有相同位的浮点数:

union {
    void *p;
    double d;
} u;
    ...
u.p = p;
phy_address = u.d;

然而,有些数字(例如0)在double数据类型中有两个不同的表示。这意味着有两种不同的位组合(因此有两个不同的地址)将生成相同的数字。

由于这个原因,不能有任何方法将64位值转换为double值,从而产生唯一的double值:数据类型double具有少于2 ^ 64个不同的值!

更糟糕的是:

有特殊值 - 所谓的“NaN”值。并且有很多!

我刚做了以下测试:

// Write a "NaN" value to a
...
b = a;
if(a == b) puts("equal");
if(a != b) puts("not equal");
// Check if a and b still contain the same value
...

......我得到的结果“不相等”,尽管最后的检查说ab仍然包含相同的值!

根据您的环境,某些NaN值(所谓的“信令NaN”值)甚至可能导致程序崩溃!

结论

就个人而言,我绝不会将浮点数据类型用作“唯一标识符”。

在你的情况下,我会直接使用void *作为“唯一标识符”。如果这是不可能的,我会使用一些64位整数数据类型,因为“Stuart”已在他的回答中提出。

© www.soinside.com 2019 - 2024. All rights reserved.