0

I have the following code:

void (* point)();
point=prova;
unsigned long int imm8 = point<<24;

...
void prova(){
...
}

The third line of code I have error:

invalid operands to binary << (have 'void (*)()' and 'int')

I'm trying to apply the shift operator to a function pointer, but I get the following error. how can I do?

yizzlez
  • 8,757
  • 4
  • 29
  • 44
pask
  • 27
  • 3
  • 10
    Why would you want to bit shift a pointer to a function? – crashmstr Jun 03 '14 at 15:15
  • 1
    You cannot bit shift a pointer. It doesn't even make sense. If you must live dangerous, cast the pointer to `uintptr_t`. – Siyuan Ren Jun 03 '14 at 15:16
  • Clearly you don't fully understand what you are attempting here. Now is the time for you to explain your motivation for asking the question. – David Heffernan Jun 03 '14 at 15:17
  • @pask I agree with the others. Although I have provided a working solution, you still need to say **why** you're doing what you're doing. Although there seems to be a troll here downvoting all actual answers, you still need to declare what exactly you're trying to achieve here. – AStopher Jun 03 '14 at 15:21
  • I have to concur that editing your question to explain your goal would help. – Shafik Yaghmour Jun 03 '14 at 19:30
  • @C.R.: The language doesn't guarantee that you can convert a function pointer to `uintptr_t` without loss of information. That guarantee applies only to `void*` (and implicitly for other object pointer types, but function pointers can have a completely different representation). It will typically work, but it's not guaranteed. (And it's a very silly thing to do anyway.) – Keith Thompson Jun 03 '14 at 19:39
  • @KeithThompson: OK, then `uintmax_t`. – Siyuan Ren Jun 04 '14 at 00:35
  • @C.R.: No, there's no guarantee that `uintmax_t`, or *any* integer type, is big enough to hold a converted pointer without loss of information. (I have yet to see an implementation where it isn't, though.) – Keith Thompson Jun 04 '14 at 00:43

3 Answers3

3

I don't see why you want to do this but the error is correct, the draft C++ standard in section 5.8 Shift operators says;

The operands shall be of integral or unscoped enumeration type and integral promotions are performed.[...]

You can use reinterpret_cast to convert it to an integral type(uintptr_t) if needed. The linked reference contains the following example:

int i = 7;

// pointer to integer and back
uintptr_t v1 = reinterpret_cast<uintptr_t>(&i); // static_cast is an error

Warning

This type of conversion is only conditionally supported, we can see this from the C++ draft standard section 5.2.10 Reinterpret cast which says:

Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cv- qualification, shall yield the original pointer value.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • There's no guarantee that you can convert a function pointer to `uintptr_t` without loss of information. (There is such a guarantee for `void*`.) – Keith Thompson Jun 03 '14 at 19:39
  • @KeithThompson thank you for that comment, I see now that it is conditionally supported. Let me add the standard quote. – Shafik Yaghmour Jun 03 '14 at 19:53
2

There is no portable way to do this.

The standard guarantees that you can convert a void* to uintptr_t without loss of information -- but it doesn't guarantee that uintptr_t exists. A conforming implementation might not have an integer type wide enough to hold a converted pointer without loss of information.

And even if uintptr_t exists, the language only guarantees that you can convert void* to uintptr_t without loss of information. A conforming permission might have, for example, 64-bit object pointers, 64-bit uintprt_t, and 128-bit function pointers.

It's likely, in most implementations, that you can convert a function pointer to uintptr_t without loss of information. (I think POSIX guarantees this, though the ISO C and C++ standards do not.)

Once you've done that, probably using a reinterpret_cast, you have an unsigned integer, which you can shift as you like.

The result of this shift will almost certainly be meaningless garbage. C++ doesn't prevent you from shooting yourself in the foot, which is what you appear to be trying to do.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
0

There should be no valid reason for doing this. However, you can do this by first casting to unsigned long int

unsigned long int imm8 = reinterpret_cast<unsigned long int >(point)<<24;

Here reinterpret_cast is done to treat the pointer as unsigned long int. Note that it is not portable and has the possibility of data loss.

Rakib
  • 7,435
  • 7
  • 29
  • 45
  • 2
    How do you know an `unsigned long int` can hold a converted function pointer without loss of information? – Keith Thompson Jun 03 '14 at 19:40
  • @pask, each answer is about c++. However in `C` you can just cast to appropriate type `unsigned long int imm8 = (unsigned long int)point<<24;`. But as with C++, anything can happen – Rakib Jun 04 '14 at 08:55
  • @pask if you have C source, why on earth did you tag this C++? – crashmstr Jun 04 '14 at 12:32