I am trying to adapt an existing code to a 64 bit machine. The main problem is that in one function, the previous coder uses a void* argument that is converted into suitable type in the function itself. A short example:
void function(MESSAGE_ID id, void* param)
{
if(id == FOO) {
int real_param = (int)param;
// ...
}
}
Of course, on a 64 bit machine, I get the error:
error: cast from 'void*' to 'int' loses precision
I would like to correct this so that it still works on a 32 bit machine and as cleanly as possible. Any idea ?
I think the "meaning" of void* in this case is a generic handle. It is not a pointer to a value, it is the value itself. (This just happens to be how void* is used by C and C++ programmers.)
If it is holding an integer value, it had better be within integer range!
Here is easy rendering to integer:
It should only give a warning.
I came across this question while studying the source code of SQLite.
In the sqliteInt.h, there is a paragraph of code defined a macro convert between integer and pointer. The author made a very good statement first pointing out it should be a compiler dependent problem and then implemented the solution to account for most of the popular compilers out there.
And here is a quote of the comment for more details:
Credit goes to the committers.
Use
uintptr_t
as your integer type.I'd say this is the modern C++ way.
EDIT:
The correct type to the the Integer
so the right way to store a pointer as an integer is to use the
uintptr_t
orintptr_t
types. (See also in cppreference integeger types for C99).these types are defined in
<stdint.h>
for C99 and in the namespacestd
for C++11 in<cstdint>
(see integer types for C++).C++11 (and onwards) Version
C++03 Version
C99 Version
The correct casting operator
In C there is only one cast and using the C cast in C++ is frowned upon (so don't use it in C++). In C++ there is different casts.
reinterpret_cast
is the correct cast for this conversion (See also here).C++11 Version
C++03 Version
C Version
Related Questions
Since
uintptr_t
is not guaranteed to be there in C++/C++11, if this is a one way conversion you can consideruintmax_t
, always defined in<cstdint>
.To play safe, one could add anywhere in the code an assertion:
#include <stdint.h>
uintptr_t
standard type defined in the included standard header file.