is it possible to convert a function pointer to an integer? - c++

I want to do something like this in a well-defined manner:
struct S
{
static some_integral_type f() noexcept
{
return some_cast<...>(&f);
}
};
The integer can be signed or unsigned. The result should be the same as the casts of object pointers to uintptr_t or intptr_t produce. AFAIK casts to those are not guaranteed to be possible for function pointers. Even casts to uintmax_t and intmax_t might not work for all I know.
I need this so I can produce a unique "handle" from a function pointer, that I can then use in a switch statement.

In general, no.
First, member-function-pointers (and member-pointers) are hairy beasts the standard says very little about.
So, let's ignore them for now.
Next, it might not even be possible to round-trip plain old function-pointers through void*, and the standard only defines a type for round-tripping data-pointers through integers, if the implementation supports such:
(u)intptr_t.
Naturally, if your implementation has a large enough integer-type, you can manually do it by reading the pointer as an unsigned char[] and combining it to a single numeric value, the operation then being reversible.
Be aware that equal function-pointers can result in different numbers if you go that route though, as the same pointer can have multiple possible representations (for example padding bytes, non-value-bits, segmentation)...

You can attempt to select an integer of the same size as the function pointer with a metafunction- the required size being sizeof(void(*)()). However, there's no guarantee that any such integer type exists.
Realistically speaking, casting it to void* or intptr_t is gonna work on pretty much all the mainstream platforms.

Taken from Can std::hash be used to hash function pointers?
In a previous attempt I attempted to cast the function pointer to
void*, which isn't allowed and doesn't compile (see:
https://isocpp.org/wiki/faq/pointers-to-members#cant-cvt-memfnptr-to-voidptr
for details). The reason is that a void* is a data pointer, while a
function pointer is a code pointer.

Related

Can i cast method pointer to long(int, size_t)

My problem is i need to represent a pointer to class's method like integer number. So it's not problem with functions, for example void (*func)() easy cast to number, but when i trying to cast void (&SomeClass::SomeMethod) to integer with any ways compiles says it's impossible
C-style cast from 'void(ForthInterpreter::*)()' to long is not alowed
I tried (size_t)&ForthInterpreter::CodeFLiteral, static_cast<size_t>(&ForthInterpreter::CodeFLiteral) but i got the same errors. Should to suppose there is a principal differense between pointer to function and method but what is it? And how can i cast it succesfully?
I use clang++ with C++11 version.
for example void (*func)() easy cast to number
No it's not, it just looks like it on your specific machine. There are systems where a pointer is represented as two internal values, for example read about far pointers.
Not to mention the 64-bit problems you're inviting, long is different types in x64 on gcc and cl for example, two very main-stream compilers.
when i trying to cast void (&SomeClass::SomeMethod) to integer with any ways compiles says it's impossible
Absolutely, because not only a class member pointer has the same problem as above, but it absolutely requires a pointer to the object instance itself (usually passed as a register, and again usually ecx or rcx). There's no way you can represent that in a more portable way than a pointer to the correct type.
i need to represent a pointer to class's method like integer number
No you don't, you just want to. There's a difference there. The solution is to adapt to what is possible instead.
A pointer-to-member is not just a simple pointer, it is much more complex. Depending on compiler implementation, it could be 2 pointers, one to the object and one to the method. Or it could be an object pointer and an offset into a method table. And so on.
As such, a pointer-to-member simply cannot be stored as-is in an integer, like you are attempting to do. So you need to find another solution to whatever problem you are trying to solve by storing a pointer inside an integer.

Properly casting a `void*` to an integer in C++

I'm dealing with some code that uses an external library in which you can pass values to callbacks via a void* value.
Unfortunately, the previous person working on this code decided to just pass integers to these callbacks by casting an integer to a void pointer ((void*)val).
I'm now working on cleaning up this mess, and I'm trying to determine the "proper" way to cast an integer to/from a void*. Unfortunately, fixing the use of the void pointers is somewhat beyond the scope of the rework I'm able to do here.
Right now, I'm doing two casts to convert from/to a void pointer:
static_cast<int>(reinterpret_cast<intptr_t>(void_p))
and
reinterpret_cast<void *>(static_cast<intptr_t>(dat_val))
Since I'm on a 64 bit machine, casting directly ((int)void_p) results in the error:
error: cast from 'void*' to 'int' loses precision [-fpermissive]
The original implementation did work with -fpermissive, but I'm trying to get away from that for maintainability and bug-related issues, so I'm trying to do this "properly", e.g. c++ casts.
Casting directly to an int (static_cast<int>(void_p)) fails (error: invalid static_cast from type 'void*' to type 'int'). My understanding of reinterpret_cast is that it basically just causes the compiler to treat the address of the value in question as the cast-to data-type without actually emitting any machine code, so casting an int directly to a void* would be a bad idea because the void* is larger then the int (4/8 bytes respectively).
I think using intptr_t is the correct intermediate here, since it's guaranteed to be large enough to contain the integral value of the void*, and once I have an integer value I can then truncate it without causing the compiler to complain.
Is this the correct, or even a sane approach given I'm stuck having to push data through a void pointer?
I think using intptr_t is the correct intermediate here, since it's guaranteed to be large enough to contain the integral value of the void*, and once I have an integer value I can then truncate it without causing the compiler to complain.
Yes, for the reason you mentioned that's the proper intermediate type. By now, if your implementation doesn't offer it, you probably have more problems than just a missing typedef.
Is this the correct, or even a sane approach given I'm stuck having to push data through a void pointer?
Yes, given the constraints, it's quite sane.
You might consider checking the value fits instead of simply truncating it upon unpacking it from the void* in debug-mode, or even making all further processing of that integer use intptr instead of int to avoid truncation.
You could also consider pushing a pointer to an actual int instead of the int itself though that parameter. Be aware that's less efficient though, and opens you to lifetime issues.
Based on your question, I am assuming that you call a function in some library, passing it a void*, and at some point later in time, it calls one of your functions, passing it that same void*.
There are basically two possible ways to do this; the first is through explicit casting, as you showed in your current code.
The other, which Deduplicator alluded to, is a little less efficient, but allows you to maintain control of the data, and possibly modify it between when you call the library function, and when it calls your callback function. This could be achieved with code similar to this:
void callbackFunction(void* dataPtr){
int data = *(int*)dataPtr;
/* DO SOMETHING WITH data */
delete dataPtr;
}
void callLibraryFunction(int dataToPass){
int* ptrToPass = new int(dataToPass);
libraryFunction(ptrToPass,callbackFunction);
}
Which one you should use depends on what you need to do with the data, and whether the ability to modify the data could be useful in the future.
"Is this the correct, or even a sane approach given I'm stuck having to push data through a void pointer?"
Well, regarding correct and sane its seriously debatable, especially if you are the author of the code taking the void* in the interface.
I think using intptr_t is the correct intermediate here, since it's guaranteed to be large enough to contain the integral value of the void*, and once I have an integer value I can then truncate it without causing the compiler to complain.
Yes, that's the right type to use with a reinterpret_cast<intptr_t>, but you'll need to be sure, that a intptr_t pointer type has been passed in, and the address is valid and doesn't go out of scope.
It's not so unusual to stumble over this problem, when interacting with c API's, and these are offering callbacks, that allow you to pass in user-data, that will be handled transparently by them, and never are touched, besides of your entry points1.
So it's left up to the client code being sure about how that void* should be re-interpreted safely.
1) A classical example for this kind of situation, is the pthread_create() function
You have little choice but to use static and reinterpret cast here. Casting to an int will result in loss of precision, which is never ideal. Explicitly casting is always best avoided, because sooner or later what is being casted can change and there will be no compiler warnings then. But in this case you understandably have no choice. Or do you?
You can change the callback definitions on your side to be intptr_t or long int rather than void*, and it should then work and you will not have to do any type casts...

function and member function pointers inside arithmetic types

For object pointers, we have std::intptr_t and std::uintptr_t from <cstdint>, but those don't need to fit either the function pointers nor the member function pointers. Once could write a metaprogram to find the right fit among the arithmetic types and use the correct alignment, but AFAIK no arithmetic type is guaranteed to fit. One could use an additional level of indirection and use an ordinary pointer to object. One could use an array, say char[], with an appropriate alignment. What does the standard say? Is an arithmetic type, that fits either of the two pointer types, guaranteed to exist?
EDIT:
I need this to pass a pointer into Javascript, disguised as a value of arithmetic type, then pass it back into C++, where I'd convert the value back into a pointer.
I technically won't answer your question, because I think you're asking the wrong one.
Here are the main problems with what you're doing:
Never try to store an address directly in an integral data type, you have no guarantee that it'll work.
Don't store pointers to your data in other places (e.g. files, network, other programs), there's no guarantee that the pointed data will exist when that value is needed.
Store your pointers in a local container and pass around an identifier to the right pointer.
For example, you could use a std::map<int, boost::any> for that and give the scripting language the integer key.
This fixes both mentioned issues.

Why can't you do bitwise operations on pointer in C, and is there a way around this?

I read that you can't do bitmasks on pointers, how come you can't do
bitwise operations on pointers?
Is there any way to achieve the same effect?
Does the same apply to C++?
The reason you can't do bitwise pointer operations is because the standard says you can't. I suppose the reason why the standard says so is because bitwise pointer operations would almost universally result in undefined or (at best) implementation-defined behavior. So there would be nothing you could do that is both useful and portable, unlike simpler operations like addition.
But you can get around it with casting:
#include <stdint.h>
void *ptr1;
// Find page start
void *ptr2 = (void *) ((uintptr_t) ptr1 & ~(uintptr_t) 0xfff)
As for C++, just use reinterpret_cast instead of the C-style casts.
It's disallowed because the semantics aren't really well defined. You can certainly do it, though. Just cast to uintptr_t, do the operations and then cast back into a pointer type. That will work in C++, too.
You can't use bitwise operators on pointers because the standards impose very few requirements on how a pointer is represented and what range of values any particular pointer may address. So there's no definition of what it would mean to use those operators on a pointer.
Nevertheless, most compilers on most machines use the obvious mapping of the memory address as the value of the pointer. And most of those will let you cast a pointer to an integral type. You can then do bitwise operations on the value, and even cast it back to a pointer. But that won't be strictly portable or well-defined in general.

Can I read any readable valid memory location via a (unsigned) char* in C++?

My search foo seems lacking today.
I would like to know if it is legal according to std C++ to inspect "any" memory location via an (unsigned(?)) char*. By any location I mean any valid address of an object or array (or inside an array) inside the program.
By way of example:
void passAnyObjectOrArrayOrSomethingElseValid(void* pObj) {
unsigned char* pMemory = static_cast<unsigned char*>(pObj)
MyTypeIdentifyier x = tryToFigureOutWhatThisIs(pMemory);
}
Disclaimer: This question is purely academical. I do not intend to put this into production code! By legal I mean if it's really legal according to the standard, that is if it would work on 100% of all implementations. (Not just on x86 or some common hardware.)
Sub-question: Is static_cast the right tool to get from the void* address to the char* pointer?
C++ assumes strict aliasing, which means that two pointers of fundamentally different type do not alias the same value.
However, as correctly pointed out by bdonlan, the standard makes an exception for char and unsigned char pointers.
Thus, in general this is undefined behaviour for any pointer type to read any deliberate address (which might be any type), but for the particular case of unsigned char as in the question it is allowed (ISO 14882:2003 3.10(15)).
static_cast does compile-time type checking, so it is unlikely to always work. In such a case, you will want reinterpret_cast.
Per ISO/IEC 9899:1999 (E) ยง6.5/7:
7. An object shall have its stored value accessed only by an lvalue expression that has one of
the following types:
a type compatible with the effective type of the object,
[...]
a character type
So it is legal (in C) to dereference and examine a (valid) pointer via unsigned char. However, the contents you'll find there are unspecified; tryToFigureOutWhatThisIs has no well-defined way of actually figuring out what it's looking at. I don't have a copy of the C++ spec here, but I suspect it uses the same definition, in order to maintain compatibility.
You can only use a char*, not an unsigned char*. Using an unsigned char* will break strict aliasing rules and invoke undefined behaviour, but there is an exception for char*. However, trying to actually do anything with the memory you read is very highly dubious and very likely to do something undefined. That's why it's rarely done in idiomatic C++ code.