更改函数指针的地址值

我在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状态。

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

你可能会这样写:

 typedef int (*fptr)(int, int); functionPtr = (fptr)(((intptr_t) functionPtr) | 1); 

您正在寻找的行为是更合理的结果之一,但同样,两个演员的行为都是未定义的 。 因此,通过修改的指针执行函数调用所期望的行为 – 如果你的程序甚至可以达到那么远 – 也是未定义的。 即使接受代码也不需要编译器。

可能,这是一个坏主意,但如果你真的需要这个,以下可以做到这一点:

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

但请注意,这不是便携式的,并且可能在您的环境中工作或根本不工作。

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

生成支持在ARM和Thumb指令集之间进行调用的代码。 如果没有此选项,则在v5之前的体系结构中,两个指令集无法在一个程序中可靠地使用。 默认为-mno-thumb-interwork,因为在指定-mthumb-interwork时会生成稍大的代码。 在AAPCS配置中,此选项毫无意义。

函数指针格式取决于体系结构和实现。

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