I am trying to implement an abstract interface in C using function pointers inside a struct.
Something like the following
typedef int (*fn_t)(int);
typedef struct
{
int x;
const fn_t fnp;
}struct_t;
__attribute__((optimize("O0"))) int square(int num)
{
return num * num;
}
static struct_t test = {.fnp = square};
int main(void)
{
test.x = 1;
int fnp_ret = test.fnp(3);
return (fnp_ret);
}
当使用ARM—GCC—13.2.0 unknown—eabi使用—O3构建godbolt时,输出如下.
square:
str fp, [sp, #-4]!
add fp, sp, #0
sub sp, sp, #12
str r0, [fp, #-8]
ldr r3, [fp, #-8]
mov r2, r3
mul r2, r3, r2
mov r3, r2
mov r0, r3
add sp, fp, #0
ldr fp, [sp], #4
bx lr
main:
mov r1, #1
ldr r3, .L5
mov r0, #3
ldr r2, [r3, #4]
str r1, [r3]
bx r2
.L5:
.word .LANCHOR0
这里可以看到,在main()
中,程序集发出,首先在 struct 中定位函数指针,然后取消引用它.我觉得这很奇怪,因为函数指针是const
,所以我希望编译器应该弄清楚它总是指向square
函数,这样就相当于直接调用square
函数.显然这里不是这样.
在实验过程中,我注意到,如果语句test.x = 1;
被注释掉,程序集通过直接调用square
函数,
square:
str fp, [sp, #-4]!
add fp, sp, #0
sub sp, sp, #12
str r0, [fp, #-8]
ldr r3, [fp, #-8]
mov r2, r3
mul r2, r3, r2
mov r3, r2
mov r0, r3
add sp, fp, #0
ldr fp, [sp], #4
bx lr
main:
mov r0, #3
b square
What am I missing?
Is there any way to implement this reliably without paying the performance hit described above?