简体   繁体   English

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

[英]How to get the Physical address of a C pointer as a value?

in my system, 在我的系统中

sizeof(void*) = 8 bytes

size of all pointer types is 8 bytes. 所有指针类型的大小为8个字节。

I have this struct 我有这个结构

struct element{void* value};

so this struct is jus a pointer value of 8 bytes. 所以这个结构是一个8字节的指针值。

since all type of pointers have 8 bytes, I should be able to just assign the physical address of any type of variable to this void* value 由于所有类型的指针都有8个字节,因此我应该能够将任何类型的变量的物理地址分配给该void *值

also, 也,

sizeof(double) = 8 bytes;

question is how do I obtain the physical address of any pointer as a double value and then assign this value to any other 8 byte pointer. 问题是如何获取任何指针的物理地址作为双精度值,然后将此值分配给任何其他8字节指针。

so say, 所以说,

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. */

Is it possible to typecast it as int* or any other pointer type? 是否可以将其转换为int *或任何其他指针类型? its jus an address... 它是一个地址...

On most systems there is an integer type that is the same size as a void * . 在大多数系统上,有一个整数类型,其大小与void *相同。 Usually this type is int or long int or long long int . 通常,此类型为intlong intlong long int Most compilers will provide the type, intptr_t (and its unsigned cousin uintptr_t ), that is a typedef of one of these types. 大多数编译器都会提供intptr_t类型(及其无符号的表亲uintptr_t ),即这些类型之一的typedef。 I think people prefer to use uintptr_t because negative address values usually don't make sense. 我认为人们更喜欢使用uintptr_t因为负地址值通常没有意义。 Anyway you should probably use this type instead of double. 无论如何,您可能应该使用此类型而不是double。

Remember that uintptr_t is just one of the regular integer types, so once you get the pointer value into a variable of this type, you can do any integer arithmetic you like. 请记住, uintptr_t只是常规整数类型之一,因此一旦将指针值放入该类型的变量中,就可以执行任意喜欢的整数运算。 As for how to get the pointer value into a uintptr_t, see this question/answer, Converting a non-`void` pointer to `uintptr_t` and vice-versa . 至于如何将指针值转换为uintptr_t,请参见以下问题/答案, 将非void指针转换为uintptr_t,反之亦然

I use= these values can be used as unique identifier in a table. 我使用=这些值可以用作表中的唯一标识符。

OK. 好。 This information is necessary because there is no possibility to convert a pointer into a floating-point number with any meaningful value; 该信息是必需的,因为不可能将指针转换为具有任何有意义值的浮点数; the floating-point number will have a meaningless value in any way. 浮点数无论如何都将没有意义。

There are two possibilities to convert a pointer to a (meaningless) floating-point value but in both cases you are not guaranteed that two floating-point numbers are unique for two different pointers! 有两种将指针转换为(无意义的)浮点值的可能性,但是在两种情况下,都不能保证两个浮点数对于两个不同的指针是唯一的!

Possibility 1: 可能性1:

Convert the pointer to an integer and the integer to floating-point: 将指针转换为整数,并将整数转换为浮点数:

phy_address = (double)(uintptr_t)p;

However as Weather Vane already mentioned in his comment double values have a limited precision. 但是,正如Weather Vane在其评论中已经提到的, double精度值的精度有限。

The integer values (addresses) 12345678901234567 80 and 12345678901234567 90 would both be rounded to 12345678901234567 68 .0. 整数值(地址)12345678901234567 80和12345678901234567 90 将四舍五入为12345678901234567 68 .0。

Possibility 2: 可能性2:

Because both double and pointers are 64 bits wide you could generate a floating-point number that has the same bits as the pointer: 因为double和指针均为64位宽,所以您可以生成一个与指针具有相同位的浮点数:

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

However there are numbers (for example the 0 ) which have two different representations in the double data type. 但是,有一些数字(例如0 )在double数据类型中具有两种不同的表示形式。 This means that there are two different combinations of bits (and therefore two different addresses) that will generate the same number. 这意味着将使用两种不同的位组合(因此,将使用两个不同的地址)来生成相同的数字。

For this reason there cannot be any method to convert a 64-bit value into a double value resulting in an unique double value: The data type double has less than 2^64 different values! 因此, 没有任何方法可以将64位值转换为double精度值,从而导致唯一的double精度值:数据类型double不同值小于2 ^ 64!

And it is even worse: 更糟糕的是:

There are special values - so called "NaN" values. 有特殊值-所谓的“ NaN”值。 And there are a lot of them! 而且有很多!

I just did the following test: 我只是做了以下测试:

// 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
...

... and I get the result "not equal" although the check at the end says that a and b still contain the same value! ...尽管最后的检查显示ab仍然包含相同的值,但我得到的结果“不相等”!

Depending on your environment some NaN values (so-called "signalling NaN" values) might even cause your program to crash! 根据您的环境,某些NaN值(所谓的“ signaling NaN”值)甚至可能导致程序崩溃!

Conclusion 结论

Personally I would never use floating-point data types as "unique identifier". 我个人绝不会将浮点数据类型用作“唯一标识符”。

In your case I would directly use void * as "unique identifier". 在您的情况下,我将直接使用void *作为“唯一标识符”。 If this is not possible I would use some 64-bit integer data type as "Stuart" already suggested in his answer. 如果这不可能,我将使用他的答案中已经建议的一些64位整数数据类型作为“ Stuart”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM