Я пишу свой собственный код инициализации, который должен пересекать массив глобальных конструкторов и вызывать их. Указатели на эти конструкторы сохраняются в разделе .init_array. Мой код выглядит следующим образом:C extern pointer to function pointer
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 void (*_init_array_start[0])();
extern void (*_init_array_end[0])();
Итак, почему компилятор разыменования указателей в первую очередь, и почему это не сделать это с синтаксис массива? Разве эти два синтаксиса не должны быть эквивалентными?