带GCC的函数指针,分配地址

时间:2012-02-01 09:22:57

标签: c gcc function-pointers

我遇到了一些我完全不明白的事情。 有一个函数原型:

typedef void ( * TMain ) ( void );

和一个函数变量:

TMain myFunc = MyFunc;
...
myFunc ();

当然,这很好用。为什么不呢。

从MAP文件中我知道“MyFunc”位于0x20100位置。 而现在有趣的事情。在赋值“myFunc = MyFunc;”之后变量“myFunc”包含值0x20100,而是0x20101!

我的问题是,我需要调用一个函数,我从表中知道地址。所以我认为我可以这样做

myFunc = ( TMain ) myTable [ 5 ];    // that would be 0x20100
myFunc ();                           // which produces a proper crash

但是,如果我这样做

myFunc = ( TMain ) ( ( Int8 * ) myTable [ 5 ] + 1 );  
myFunc ();

然后它有效。

这里发生了什么?我是否总是要添加1的偏移量,或者这或多或少是偶然的? 或者有更好的(和工作)方式来完成任务吗?

非常感谢任何提示。 沃尔特

2 个答案:

答案 0 :(得分:4)

我的猜测是你在ARM目标上并且已经在Thumb模式下构建了程序? (Thumb是ARM Ubuntu或Linaro的默认设置。)

函数地址的最低位告诉CPU应该在哪个指令集中解释该函数。 0是ARM模式。 1是拇指模式。因此,所有Thumb模式函数指针都将是奇数。

其他架构也以这种或那种方式使用这种习语。通常只需将地址的底部两位置零(使其为4字节对齐)并假设这是函数的真实位置是安全的。

答案 1 :(得分:3)

多个CPU架构为特定目的保留函数的第一个字节。 VAXen在那里有一个保存寄存器掩码。 CDC Cyber​​将回信地址放在那里。有些人使用“地址”的一些位来表示地址间接(我不记得哪些,但它们来自20世纪70年代)。

除非你真的知道自己在做什么,否则你不应该编写执行那种指针运算的代码。为变量分配函数名称并使用它完成:这保证可以在每个C实现上运行。