0

in my system,

sizeof(void*) = 8 bytes

size of all pointer types is 8 bytes.

I have this struct

struct element{void* value};

so this struct is jus a pointer value of 8 bytes.

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

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.

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? its jus an address...

  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/162146/discussion-on-question-by-nelson-aka-spooky-how-to-get-the-physical-address-of-a). – Bhargav Rao Dec 29 '17 at 07:44
  • You may just try `memcpy (&phy_address, &element.value, sizeof (void*))`. But this is weird. – Innokentiy Alaytsev Dec 29 '17 at 08:19
  • 1: 'physical address' is wrong word for it. Virtual address or logical address is correct. 2. I understand Double is not good choice of data type here. What about just an array of bytes? How do I convert to array of 8 bytes - the quickest way possible without much intermediate conversion. – Nelson aka SpOOKY Dec 29 '17 at 13:12

2 Answers2

1

On most systems there is an integer type that is the same size as a void *. Usually this type is int or long int or long 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. I think people prefer to use uintptr_t because negative address values usually don't make sense. Anyway you should probably use this type instead of 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. 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.

Stuart
  • 1,428
  • 11
  • 20
0

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:

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.

The integer values (addresses) 1234567890123456780 and 1234567890123456790 would both be rounded to 1234567890123456768.0.

Possibility 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:

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

And it is even worse:

There are special values - so called "NaN" values. 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!

Depending on your environment some NaN values (so-called "signalling NaN" values) might even cause your program to crash!

Conclusion

Personally I would never use floating-point data types as "unique identifier".

In your case I would directly use void * as "unique identifier". If this is not possible I would use some 64-bit integer data type as "Stuart" already suggested in his answer.

Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38