views:

357

answers:

9

I know that converting a pointer to one int is unsafe, because the pointer can be bigger than the int in some architectures (for instance in x86_64).

But what about converting the pointer to several ints, an array of them? If the pointer size is 2 times bigger than int then convert pointer* to int[2].

The number of needed ints then is ceil(sizeof(pointer*)/sizeof(int)).

I need to do this because there is a function which takes ints as arguments and I want to pass a pointer to it.

A: 

Why do you want to do this? Surely there has to be a better way. Please provide more detail.

1800 INFORMATION
Shouldn't this be a comment?
anon
A: 

if a function takes an array of ints, then yes you can manually detect the size of void* versus the size of int on your machine and save your pointer to array[0] + array[1], etc.

It's a bit hard to tell what's really needed from your description. What will the function do? Will you have to handle big/little-endian difference, for example?

n-alexander
A: 

I have macros for this:

#define DIM_ARR(arr) (sizeof(arr) / sizeof(arr[0]))

Even if array is empty - this construction (sizeof(arr[0])) resolved on compile time - that is why you will get correct size

Dewfy
A: 
StampedeXV
Thanks, that's what I want to do. Anyone know of a generic version of this code?
Helltone
now with generic also. edited.
StampedeXV
hm. Large part of the edit is missing. repost as new answer.
StampedeXV
A: 

you said you want to pass a pointer to a function with int as arguments.
If your pointer points to an integer or character or float you can always dereference it, caste it and pass by value.
Or, if you really want to pass by address, then modify the function definition to take pointer as argument.

Or, if you are using some library function then you are on the wrong way man.

And even you convert it to an array of ints, how are going to pass the array?, array are always passed by address.

Neeraj
A: 

Doesn't your platform provide a intptr_t ?

tristopia
Why the down vote? It's an appropriate question. If his compiler platform provides the intptr_t his question is moot. Otherwise the other responses he got are OK.
tristopia
Yes I have intptr_t.
Helltone
So, if your platform has it, then you do not need to split your pointers on ints. The standard guarantees that it can hold a void *.That's what the standard says:7.18.1.4 Integer types capable of holding object pointers1 The following type designates a signed integer type with the property that any validpointer to void can be converted to this type, then converted back to pointer to void,and the result will compare equal to the original pointer:intptr_tThese types are optional.
tristopia
Good answer, but not portable. And I understand portability is part of the issue.
Gorpik
+1  A: 

What about something like this:

void *pointer = (void*) 0x0123456789ABCDEFULL;

// 4 int's max, I don't know how to do it in a generic way
assert(sizeof(pointer) <= 4*sizeof(int));

int buffer[4]; // copy from pointer to buffer
memcpy(buffer, &pointer, sizeof(pointer));

// call the function
f(buffer[0], buffer[1], buffer[2], buffer[3]);

// how to recover the value of the pointer
void f(int b0, int b1, int b2, int b3) {
   int buffer[4] = {b0, b1, b2, b3};
   void *pointer; // copy from buffer to pointer
   memcpy(&pointer, buffer, sizeof(test_pointer));
}
Helltone
+2  A: 

Fairly robust & portable:

void* p = foo();
std::vector<int> buf(sizeof(p));
std::copy(reinterpret_cast<char*>(&p),
          reinterpret_cast<char*>(&p) + sizeof(p),
          buf.begin());
MSalters
Can you explain what it does? lol
Helltone
Please add some comments and explain what it does.
Helltone
The reinterpret_cast treats the void* as a char[], typically a char[4] or char[8]. The std::copy copies these to a vector<int> with the same number of elements. The whole process can be reversed by swapping std::copy's source and destination.
MSalters
A: 

Yet another solution:

#define BIG_ENOUGH 4

typedef union {
   int buffer[BIG_ENOUGH];
   pointer_t* pointer;
} proxy_t;

static_assert(sizeof(pointer_t*) <= BIG_ENOUGH*sizeof(int));

// before calling the function

proxy_t proxy;
proxy.pointer = the_pointer;

// call to the function, cannot be generic here
f(proxy.buffer[0], proxy.buffer[1], proxy.buffer[2], proxy.buffer[3]);

// how to recover the value of the pointer
void f(int b0, int b1, int b2, int b3) {

  proxy_t proxy = { { b0, b1, b2, b3 } };

  the_pointer = proxy.pointer;

}
Helltone
This seems to be fairly portable.
Helltone