6

I have an array of unsigned integers that need to store pointers to data and functions as well as some data. In the device I am working with, the sizeof pointer is the same as sizeof unsigned int. How can I cast pointer to function into unsigned int? I know that this makes the code not portable, but it is micro controller specific. I tried this:

stackPtr[4] = reinterpret_cast<unsigned int>(task_ptr);

but it give me an error "invalid type conversion"

Casting it to void pointer and then to int is messy.

stackPtr[4] = reinterpret_cast<unsigned int>(static_cast<void *> (task_ptr));

Is there a clean way of doing it?

Edit - task_ptr is function pointer void task_ptr(void)

Love Barmar's answer, takes my portability shortcoming away. Also array of void pointer actually makes more sense then Unsigned Ints. Thank you Barmar and isaach1000.

EDIT 2: Got it, my compiler is thinking large memory model so it is using 32 bit pointers not 16 bit that I was expecting (small micros with 17K total memory).

6
  • 1
    Can't you make the array an array of void pointers? Commented May 6, 2013 at 15:07
  • 4
    How about using a union of function pointers and data pointers? Commented May 6, 2013 at 15:09
  • 1
    A simple reinterpret_cast should work as long as (a) the integer type is large enough and (b) it's a pointer to a normal (non-member, or static member) function. Is that the case here? What exactly is task_ptr? Commented May 6, 2013 at 15:20
  • Wow, Barmar, that would make my code portable! This is a major case of tunnel vision on my part. Thanks a million, your comment is worth 1000+ Commented May 6, 2013 at 16:10
  • 1
    void(void) isn't a pointer type, it's a function type. The corresponding pointer type is void(*)(void). Commented May 6, 2013 at 16:59

3 Answers 3

4

A C-style cast can fit an octogonal peg into a trapezoidal hole, so I would say that given your extremely specific target hardware and requirements, I would use that cast, possibly wrapped into a template for greater clarity.

Alternately, the double cast to void* and then int does have the advantage of making the code stand out like a sore thumb so your future maintainers know something's going on and can pay special attention.

EDIT for comment: It appears your compiler may have a bug. The following code compiles on g++ 4.5:

#include <iostream>

int f()
{
    return 0;
}

int main()
{
    int value = (int)&f;

    std::cout << value << std::endl;
}

EDIT2: You may also wish to consider using the intptr_t type instead of int. It's an integral type large enough to hold a pointer.

Sign up to request clarification or add additional context in comments.

2 Comments

The C++ compiler returns an error when I use C style cast: Error[Pe171]: invalid type conversion
Unfortunately, intptr_t is not specified to allow the reconstitution of converted function pointers the way it is for object pointers, and there is no equivalent for function pointers, either :-(. So, there's no obvious way to ensure that your code will fail to compile on systems where function pointers won't fit in intptr_t.
2

In C++ a pointer can be converted to a value of an integral type large enough to hold it. The conditionally-supported type std::intptr_t is defined such that you can convert a void* to intptr_t and back to get the original value. If void* has a size equal to or larger than function pointers on your platform then you can do the conversion in the following way.

#include <cstdint>
#include <cassert>

void foo() {}

int main() {
    void (*a)() = &foo;

    std::intptr_t b = reinterpret_cast<std::intptr_t>(a);

    void (*c)() = reinterpret_cast<void(*)()>(b);
    assert(a==c);
}

1 Comment

It's also conditionally-supported whether or not a can be reinterpret-cast to b, even if intptr_t exists. (However it is guaranteed that if such support exists, then a == c).
-1

This is ansi compliant:

int MyFunc(void* p)
{
    return 1;
}

int main()
{
   int arr[2];
   int (*foo)(int*);

   arr[0] = (int)(MyFunc);

   foo = (int (*)(int*))(arr[0]);

   arr[1] = (*foo)(NULL);
}

3 Comments

Tried that, but my C++ complains, invalid type conversion. Need a standard C++ way of doing it.
Last time I checked, void main() was non-standard.
I am using the IAR Embedded Workbench. https://www.iar.com/en/Products/IAR-Embedded-Workbench/TI-MSP430/ but I think I know why it is not working, it is thinking of larger memory model then I am using, which makes the pointers 20bit instead of 16. So yes, you are right, its the compiler issue. The MinGW compiler has no problems.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.