0

我在 C 中有以下代码:

int addInt(int n, int m) {
    return n + m;
}

int (*functionPtr)(int, int);

functionPtr = &addInt;

functionPtr是一个函数指针,它指向函数addInt的特定地址。我想更改其值的 1 位,但我无法弄清楚如何。

假设functionPtr在最后一条语句之后指向0xABC0(假设是 16 位地址)。我想将其值更改为0xABC1。我试图用 0x1 对值进行 OR 运算,但我猜操作数转换有问题:

functionPtr = &addInt | 0x00000001; // addresses are of 32 bits

我知道搞乱指针是有风险的,但我必须更改地址的 LSB 才能进入 ARM Cortex-M4 MCU 的 Thumb 状态。

4

4 回答 4

1

要通过算术运算修改指针的值,您需要将其转换为整数类型,执行操作,然后将其转换回来。但是,C 没有定义将函数指针转换为另一个函数指针以外的任何东西的行为,因此没有定义的方法来做到这一点。

你仍然可以这样写:

typedef int (*fptr)(int, int);

functionPtr = (fptr)(((intptr_t) functionPtr) | 1);

您正在寻找的行为是更合理的结果之一,但同样,两种强制转换的行为都是undefined。因此,通过修改后的指针执行函数调用的预期行为——如果你的程序甚至可以达到那么远——也是未定义的。编译器甚至不需要接受代码。

于 2015-10-06T17:39:48.303 回答
0

可能,这是一个坏主意,但如果你真的需要这个,以下可以解决问题:

functionPtr = &addInt;
*(int*)&functionPtr |= 1;

但请注意,这不是可移植的,在您的环境中可能工作或根本不工作。

于 2015-10-06T17:36:21.077 回答
0

许多人提到你的方法很危险,但在某些情况下,这是一个真正的问题,我不止一次遇到过。我怀疑目前您的代码使用BL不会将 CPU 模式更改为 thumb 的指令(分支和链接),以便根据您的函数指针执行从 ARM 到 thumb 的调用,将-mthumb-interwork标志添加到 gcc 时编译你的代码:

生成支持 ARM 和 Thumb 指令集之间调用的代码。如果没有这个选项,在 v5 之前的架构上,两个指令集就不能在一个程序中可靠地使用。默认值为 -mno-thumb-interwork,因为在指定 -mthumb-interwork 时会生成稍大的代码。在 AAPCS 配置中,此选项没有意义。

于 2015-10-06T17:56:47.907 回答
-2

函数指针格式取决于架构和实现。

例如,在 Itanium 上,函数指针指向一个只读数据结构,其中包含函数所属模块的适当全局指针,以及实际的函数指针。

于 2015-10-06T17:40:56.347 回答