【问题标题】:Casting Function Pointer to Integer in C++在 C++ 中将函数指针转换为整数
【发布时间】:2013-04-30 09:06:07
【问题描述】:

我有一个无符号整数数组,需要存储指向数据和函数的指针以及一些数据。在我正在使用的设备中,sizeof 指针与 sizeof unsigned int 相同。如何将指向函数的指针转换为 unsigned int?我知道这使代码不可移植,但它是特定于微控制器的。我试过这个:

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

但它给了我一个错误“无效的类型转换”

将其转换为 void 指针,然后转换为 int 很麻烦。

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

有干净的方法吗?

编辑 - task_ptr 是函数指针void task_ptr(void)

Love Barmar 的回答消除了我的便携性缺点。 void 指针数组实际上比无符号整数更有意义。谢谢 Barmar 和 isaach1000。

编辑 2:知道了,我的编译器正在考虑大内存模型,所以它使用的是 32 位指针,而不是我期望的 16 位指针(总内存为 17K 的小型微控制器)。

【问题讨论】:

  • 你不能让数组成为一个空指针数组吗?
  • 如何使用函数指针和数据指针的联合?
  • 一个简单的reinterpret_cast 应该可以工作,只要 (a) 整数类型足够大并且 (b) 它是一个指向普通(非成员或静态成员)函数的指针。这里是这样吗? task_ptr 到底是什么?
  • 哇,Barmar,这将使我的代码可移植!这是我的隧道视野的一个主要案例。感谢一百万,您的评论价值 1000+
  • void(void) 不是指针类型,而是函数类型。对应的指针类型为void(*)(void)

标签: c++


【解决方案1】:

C 样式的铸件可以将八角钉装入梯形孔中,所以我想说,鉴于您极其具体的目标硬件和要求,我会使用该铸件,可能会包裹在模板中以提高清晰度。

或者,对void*int 进行双重转换确实具有使代码突出的优势,因此您的未来维护人员可以知道正在发生的事情并可以特别注意。

编辑评论: 看来您的编译器可能有错误。以下代码在 g++ 4.5 上编译:

#include <iostream>

int f()
{
    return 0;
}

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

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

编辑2: 您可能还希望考虑使用intptr_t 类型而不是int。它是一个大到足以容纳指针的整型。

【讨论】:

  • 当我使用 C 风格转换时,C++ 编译器返回错误:Error[Pe171]: invalid type conversion
  • 不幸的是,intptr_t 没有被指定为允许以对象指针的方式重构转换后的函数指针,并且函数指针也没有等价物:-(。所以,没有确保您的代码无法在函数指针不适合 intptr_t 的系统上编译的明显方法。
【解决方案2】:

在 C++ 中,指针可以转换为整数类型的值,该值大到足以容纳它。定义了有条件支持的类型 std::intptr_t,以便您可以将 void* 转换为 intptr_t 并返回以获取原始值。如果void* 的大小等于或大于您平台上的函数指针,那么您可以通过以下方式进行转换。

#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);
}

【讨论】:

  • 即使intptr_t 存在,a 是否可以重新解释转换为b 也是有条件的支持。 (但保证如果存在这样的支持,那么a == c)。
【解决方案3】:

这是符合 ansi 的:

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);
}

【讨论】:

  • 试过了,但我的 C++ 抱怨,invalid type conversion。需要一种标准的 C++ 方法。
  • 我上次检查时,void main() 是非标准的。
  • 我正在使用 IAR Embedded Workbench。 https://www.iar.com/en/Products/IAR-Embedded-Workbench/TI-MSP430/ 但我想我知道它为什么不工作,它正在考虑比我使用的更大的内存模型,这使得指针变为 20 位而不是 16 位。所以是的,你是对的,它的编译器问题。 MinGW 编译器没有问题。
猜你喜欢
  • 1970-01-01
  • 2012-11-21
  • 2021-04-18
  • 2015-01-06
  • 2021-02-13
  • 2011-07-31
  • 1970-01-01
相关资源
最近更新 更多