【发布时间】:2013-11-17 14:36:50
【问题描述】:
我正在编写自己的初始化代码,它应该遍历一组全局构造函数并调用它们。指向这些构造函数的指针存储在 .init_array 部分中。我的代码如下所示:
extern void (**_init_array_start)();
extern void (**_init_array_end)();
void _init()
{
void (**ctor)();
for (ctor = _init_array_start ; ctor != _init_array_end ; ctor++) {
(*ctor)();
}
}
外部在链接描述文件中定义,如下所示:
.init_array :
{
. = ALIGN(4);
_init_array_start = .;
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
. = ALIGN(4);
_init_array_end = .;
} >rom
但是,最终的汇编代码如下所示:
00000010 <_init>:
10: b538 push {r3, r4, r5, lr}
12: 4b05 ldr r3, [pc, #20] ; (28 <_init+0x18>)
14: 4d05 ldr r5, [pc, #20] ; (2c <_init+0x1c>)
16: 681c ldr r4, [r3, #0]
18: 682b ldr r3, [r5, #0]
1a: 429c cmp r4, r3
1c: d003 beq.n 26 <_init+0x16>
1e: f854 3b04 ldr.w r3, [r4], #4
22: 4798 blx r3
24: e7f8 b.n 18 <_init+0x8>
26: bd38 pop {r3, r4, r5, pc}
28: 00000144 andeq r0, r0, r4, asr #2
2c: 00000150 andeq r0, r0, r0, asr r1
现在,这里有趣的部分是 0x16 和 0x18。这两条指令在循环头中取消引用 _init_array_start 和 _init_array_end。这不是我的本意。我想处理指向函数指针的指针,而不是它们的值(即直接的函数指针)。 现在,当我将 extern 声明更改为以下内容时,两个取消引用指令神奇地消失了:
extern void (*_init_array_start[0])();
extern void (*_init_array_end[0])();
那么,为什么编译器首先取消引用指针,为什么它不使用数组语法这样做呢?这两种语法不应该是等价的吗?
【问题讨论】:
标签: c arrays pointers assembly function-pointers