Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何获取C指针的物理地址作为值?_C_Pointers - Fatal编程技术网

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

如何获取C指针的物理地址作为值?,c,pointers,C,Pointers,在我的系统中 sizeof(void*) = 8 bytes 所有指针类型的大小为8字节 我有这个结构 struct element{void* value}; 所以这个结构是一个8字节的指针值 因为所有类型的指针都有8个字节,所以我应该能够将任何类型的变量的物理地址分配给这个void*值 而且 问题是如何获得任何指针的物理地址作为双精度值,然后将该值分配给任何其他8字节指针 那么说, int i; int *p = &i; struct element e; double phy_

在我的系统中

sizeof(void*) = 8 bytes
所有指针类型的大小为8字节

我有这个结构

struct element{void* value};
所以这个结构是一个8字节的指针值

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

而且

问题是如何获得任何指针的物理地址作为双精度值,然后将该值分配给任何其他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*或任何其他指针类型?它只是一个地址…

在大多数系统中,有一个整数类型的大小与
void*
相同。通常这种类型是
int
long int
long-long int
。大多数编译器将提供类型,
intptr\u t
(及其未签名的表亲
uintpr\u t
),即这些类型之一的类型定义。我认为人们更喜欢使用
uintptr\t
,因为负地址值通常没有意义。无论如何,您可能应该使用这种类型而不是double

请记住,
uintptr\u t
只是常规整数类型之一,因此,一旦将指针值放入这种类型的变量中,就可以执行任何喜欢的整数运算。关于如何将指针值输入uintptr,请参阅此问题/答案

I use=这些值可以用作表中的唯一标识符

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

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

可能性1:

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

phy_address = (double)(uintptr_t)p;
然而,正如Weather Vane在其评论中所提到的,double值的精度有限

整数值(地址)1234567890123456780和12345678900123456790都将四舍五入到12345678900123456768

可能性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
...
。。。我得到的结果是“不相等”,尽管最后的检查表明
a
b
仍然包含相同的值

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

结论

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


在您的情况下,我会直接使用
void*
作为“唯一标识符”。如果这是不可能的,我会使用一些64位整数数据类型,就像“Stuart”在他的回答中已经建议的那样。

Ty Ok。请告诉我什么是最直接的方式知道我的程序中任何进程的允许位置范围。请告诉我this@NelsonakaSpOOKY:这值得再问一个问题。评论不是为了进一步讨论;此对话已结束。您可以尝试
memcpy(&phy\u address,&element.value,sizeof(void*)
。但这很奇怪。1:“物理地址”这个词用错了。虚拟地址或逻辑地址正确。2.我知道Double不是这里数据类型的好选择。一个字节数组怎么样?如何转换为8字节数组?这是一种最快的方法,不需要太多的中间转换。谢谢,我真的不希望它是一个双字节数组。我只是想要8个字节。
// 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
...